Backend/꾸준히 TIL

[Nest.js/CSRF] 크로스 사이트 요청 위조

개발하는 후딘 2023. 1. 27. 01:22
728x90
반응형

CSRF(Cross Site Request Forgery Attack, 크로스 사이트 요청 위조 공격)

 

  • 인증된 사용자가 웹 애플리케이션에 특정 요청을 보내도록 유도공격하는 행위를 의미한다.
  • 쉽게 말하자면, 공격자의 요청이 사용자의 요청인 것처럼 속이는 공격방식 을 의미한다.

 

CSRF 공격을 어떤식으로 하는가?

공격자가 사용자인것처럼 위장하면서 요청을 보내도록 하는 것이므로

제품구입, 계정설정, 기록삭제, 비밀번호 변경, 문자 전송과 같은 데이터 값을 변경하는 요청일 때 공격한다.

  • 이메일이나 웹사이트에 하이퍼링크를 심어서 요청을 보내고 하이퍼링크를 클릭하게 되면 요청이 자동으로 전송된다.
  • 사용자 몰래 자금을 전송
  • 이메일 주소와 비밀번호를 변경하는 무단행위

 

CSRF를 어떻게 방지할까?

  • CSRF 토큰을 통해 요청이 사용자가 전송한 것이 맞는 확인하거나 재인증을 요구하는 조치를 취하고 있다.
    • 사용자 본인의 정보를 안전하게 보관하는게 제일 중요하다.
  • 사용하지 않는 웹 애플리케이션 로그아웃하기
  • 로그인 정보 안전하게 보관하기
    • 여러사이트에서 동일한 비밀번호를 사용하거나 유추하기 쉬운 비밀번호를 사용하면 위조공격에 노출될 가능성이 높다.
  • 브라우저에 비밀번호 저장하지 않기
    • CSRF는 사용자의 브라우저를 대상으로 하기때문에, 브라우저에 비밀번호를 저장하는 경우 비밀번호가 유출되어 공격대상이 될 수 있다.
    • 불편하더라도 브라우저에는 비밀번호를 저장하지 않는 것을 추천한다.
  • 여러 웹사이트 동시에 사용하지 않기
  • VPN 사용하기

 

CSRF와 XSS(Cross Site Scripting)의 공통점과 차이점

  • 공통점: 사용자의 브라우저를 대상으로 한다.
  • 차이점
    • 1) CSRF는 사용자의 인증된 세션을 악용하는 공격방식이라면 XSS는 인증된 세션없이도 공격을 진행이 가능하다.
    • 2) XSS는 사용자에서 스크립트가 실행되지만 CSRF의 요청위조는 서버에서 스크립트가 실행된다.
    • 3) XSS는 사용자의 PC에서 스크립트를 실행해 사용자의 정보를 탈취하는 것을 목적으로 하고
  • CSRF는 요청을 위조함으로써 사용자 몰래 송금과 제품구입등 특정 행위를 수행하는 것을 목적으로 한다.

 

 

Cross Site Scripting (XSS) | OWASP Foundation

Cross Site Scripting (XSS) on the main website for The OWASP Foundation. OWASP is a nonprofit foundation that works to improve the security of software.

owasp.org

 

Cross Site Request Forgery (CSRF) | OWASP Foundation

Cross Site Request Forgery (CSRF) on the main website for The OWASP Foundation. OWASP is a nonprofit foundation that works to improve the security of software.

owasp.org

 

 

[참고] Understanding CSRF 

 

GitHub - pillarjs/understanding-csrf: What are CSRF tokens and how do they work?

What are CSRF tokens and how do they work? Contribute to pillarjs/understanding-csrf development by creating an account on GitHub.

github.com

 

[참고] Difference between XSS and CSRF attacks

 

Difference between XSS and CSRF attacks

Two of the most common attacks against websites and web application are XSS (Cross-site Scripting) and CSRF (Cross-Site Request Forgery)…

l4mp1.medium.com


CSRF 공격방식을 어떻게 대비 할까?

[이미지출처] https://medium.com/a-layman 블로그

 

1. 서버에서 csrf 토큰을 생성한 뒤에 쿠키에 csrf토큰을 클라이언트에게 보내준다.

2. 클라이언트가 다시 요청을 하게되면, 서버는 csrf 토큰을 검증한다.

csrf토큰을 갖지않고 요청한다면 서버는 응답을 거부한다.

 

 

자료를 좀더 조사를 해봤더니

폼요청과 같은 post/put/delete/patch와 같은 데이터의 변경을 요구하는 api요청시

클라이언트가 서버에서 요청할 때, 무조건 프론트단에서는 csrf 토큰값을 같이 전달을 해야하며

axios나 fetch로 서버에게 요청을 한다면, 토큰과 같이 { withCredential : true } 옵션도 같이 부여하는 것이 좋다.

 

html코드에서 form요청일 경우에는 _csrf 이름으로 쿠키에 저장된 csrf토큰값을 전달하면 된다.

<form>
  <input type='hidden' name='_csrf' value='<%= csrfToken  %>'> 
  <label for='name'> Name:</label>
  <input type='text' name='name'>
  <button type='submit'> Update </button>
</form>

 

[ ncsrf 는 시도했지만, node 16 version 이상일때 충돌이 생겨서 보류하고 다른방법으로 대체했습니다. ]

더보기

 

  • 필자 사용 Node version: v18.5.0
  • 환경: mac OS

 

관련 패키지 설치하기

$ npm install ncsrf --save

 

아래와 같은 이미지로 npm 으로 ncsrf가 설치가 안되는 경우

 

(해결방안1) 옵션을 부여하여 강제설치 

원인은 패키지에서 요구하는 dependency가 일치하지 않아서 충돌이 일어난 것이다.

에러로그를 읽어보면 npm ERR! Conflicting peer dependency: @nestjs/common@8.4.7 으로 되어있고

에러로그가 해결방안도 알려준다. 

"Fix the upstream dependency conflict, or retry. this command with --force, or --legacy-peer-deps"

 

--force 옵션이나 --legecy-peer-deps 옵션을 줘서 패키지 설치하게되면 에러없이 설치가 정상적으로 된다.

# 1. --force 옵션을 사용했을 때 (충돌우회) 
# package-lock.json에 다른버젼의 의존패키지를 설치
$ npm install ncsrf --force --save


# 2. --legacy-peer-deps 옵션을 사용했을 때 (충돌무시)
$ npm instlal helmet --legacy-peer-deps

 

 

(해결방안2) nodejs version 을 다운그레이드 한다.

$ brew install node@16

 

다운그레이드 버젼의 node를 연결시킨다.

$ brew link node@16

 

node 16ver 을 다운그레이드하려고 brew를 사용하다가 발생한 문제이다

 

"You have not agreed to the Xcode license."

검색을 해보니 라이센스 미동의로 인한 문제이다. 아래 명령어를 실행시키고 다시 해보자.

$ sudo xcodebuild -license accept

 

 

[Xcode] 라이센스 미동의 오류 해결 방법 - You have not agreed to the Xcode license agreements.

안녕하세요. 즐거운 우리집 (https://joyfulhome.tistory.com/) 입니다. 오늘을 맥(MAC) 에서 git 을 사용하시면서 나오는 오류 하나를 해결하는 방법에 대해서 말씀 드리겠습니다. iOS 앱개발을 위해서는 xcod

joyfulhome.tistory.com

 

4 Step Process to Downgrade Node version using Homebrew

Certain node packages can be pretty unstable and based on your project/ teams requirements you might want to downgrade them. (In my case, I…

medium.com

 

공식다큐먼트의 예제에서도 @Csrf 라는 데코레이터로 csrf토큰이 존재하는지를 확인을 할 수 있다.

쿠키에서 _csrf 에 해당하는 값을 파싱하는 로직이 필요하다.

 

Invalid CSRF Token · Issue #6 · huy97/csrf

Hello, im using your package, when i try with postman it works but if send requests from angular im getting Invalid CSRF Token

github.com

 

ncsrf는 nodejs 16version 이상의 환경에도 빌드가 안되는 신기한 문제를 겪었다.

왜냐하면 github action에서의 빌드도 실패를 했기 때문이다.

실패 이유를 보니, node 16버젼에서 npm ci 명령어를 실행하는데 충돌이 일어났다.

0s
1s
Run npm ci
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: ncsrf@1.0.3
npm ERR! Found: @nestjs/common@9.2.0
npm ERR! node_modules/@nestjs/common
npm ERR!   @nestjs/common@"^9.0.0" from the root project
npm ERR!   peer @nestjs/common@"^8.2.3 || ^9.0.0" from @nestjs/apollo@10.1.6
npm ERR!   node_modules/@nestjs/apollo
npm ERR!     @nestjs/apollo@"^10.1.6" from the root project
npm ERR!   11 more (@nestjs/config, @nestjs/core, @nestjs/graphql, ...)
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer @nestjs/common@"^8.4.4" from ncsrf@1.0.3
npm ERR! node_modules/ncsrf
npm ERR!   ncsrf@"^1.0.3" from the root project
npm ERR! 
npm ERR! Conflicting peer dependency: @nestjs/common@8.4.7
npm ERR! node_modules/@nestjs/common
npm ERR!   peer @nestjs/common@"^8.4.4" from ncsrf@1.0.3
npm ERR!   node_modules/ncsrf
npm ERR!     ncsrf@"^1.0.3" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See /home/runner/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/runner/.npm/_logs/2023-01-26T06_01_57_011Z-debug-0.log
Error: Process completed with exit code 1.

 

nestjs 공식문서에는 csurf 도 있다. ncsrf와 달리 helmet 처럼 사용하기 편하다.

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

그래서 ncsrf 라이브러리 사용하는 대신에 csurf와 helmet을 사용하는 방안으로 했다.

 

ncsrf를 시도하다가 패키지 설치가 안되는 문제를 겪었는데, 공유하기에 좋은 주제인거같아서 잠시나마 소개를 하기로 했다 :)

npm 의 --legacy-peer-deps 와 --force 옵션의 차이점

두 옵션의 차이점이 궁금해졌다.

--legacy-peer-deps 옵션

  • 충돌 무시
  • peer-dependency 를 맞추지 않고 설치한다.
    • 즉, package-lock.json에 다른 버젼의 의존패키지를 설치하지 않는다.

 

--force 옵션

  • 충돌 우회
  • package-lock.json 에 의존버젼들을 추가

 

먼저 --force 옵션으로 인해 의존버젼을 추가하여 충돌을 우회하고, 이후에도 되지 않는다면

--legacy-peer-deps 로 충돌을 무시하여 오류없이 설치해서 실행한다.

다만, 이후에도 새로운 패키지를 설치할 때도 매번 옵션을 붙여가면서 해야되는 번거로움이 있다.

 

> stackoverflow에서 공유된 질문과 답변

 

npm: When to use `--force` and `--legacy-peer-deps`

I'm trying to understand how recreating the node_modules directory for deployment works. We're using npm ci instead of npm install to ensure a clean slate during deployment. However, when we run it

stackoverflow.com

 


1. 더이상 버젼업이 되지 않지만, 그나마 csrf 대비하는 모듈중 많이 사용한 csurf  를 사용했다.

$ npm install csurf

 

2. main.ts 에 쿠키파서 밑에 정의한다.

// main.ts


import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as cookieParser from 'cookie-parser';
import helmet from 'helmet';
import * as csurf from 'csurf';

async function bootstrap() {
  // cors(cross-origin-resource-sharing) 적용
  // 다른도메인에서 리소스 요청을 허용하게끔 한다.

  const app = await NestFactory.create(AppModule, { cors: true });
	...

  // 쿠키적용
  app.use(cookieParser());

  // csrf
  /* 
  	쿠키에 csrf Secret을 저장. '/user/'이 맨앞에 있는 url 형식을 가진 api이고
  	메소드가 post/put/delete 인 api를 요청할때 csrf 토큰이 쿠키에 존재하지 않으면 응답을 거부 
  */ 
  app.use('/user/', csurf({ cookie: { sameSite: true } }));


  // helmet 적용
  app.use(helmet());

  await app.listen(process.env.SERVER_PORT);
}
bootstrap();

 

3. csrf 토큰을 요청하는 get방식의 api를 만들기

@ApiTags('Auth')
@UseFilters(HttpExceptionFilter)
@Controller()
export class AuthController {
  constructor(
    private readonly configService: ConfigService,
    private readonly authService: AuthService,
    private readonly usersService: UsersService,
  ) {}
  	...
    
  // csrf token을 얻는다.
  @UseGuards(JwtAuthGuard) // 로그인이 되어있는 상태일 때 csrf 토큰을 발급할 수 있음.
  @Get('auth/csrf')
  async getCsrfToken(@Req() req, @Res() res: Response) {
    res.cookie('XSRF-TOKEN', req.csrfToken(), { httpOnly: true });
    return res.json({});
  }
  
  // csrf 토큰이 필요한 api
  @UseGuards(JwtAuthGuard)
  @Patch('user/:id')
  async updateUserInfo(@Req() req) {
    return { message: 'protected' };
  }
  
}

 

- cookie로 csrf토큰을 저장할 때는 XSRF-TOKEN 의 키값으로 한다.

- header로 csrf토큰을 저장할때는 X-XSRF-TOKEN 의 키값으로 한다.

 

[결과]

1) 로그인을 한다.

 

2) CSRF 토큰 발급

로그인 이후, csrf 토큰을 발급하면, 기본적으로 csurf모듈을 사용함으로써 쿠키로 생성하는 _csrf가 자동적으로 만들어지고

XSRF-TOKEN은 쿠키에서 csrf토큰을 생성방식으로 필자에 의해서 생성한거다.

 

 

3) CSRF 토큰 발급 이후, CSRF 토큰이 필요한 API 요청 테스트 (feat.  insomnia)

 

[참고] csrf토큰 구현하기

 

How to secure your web applications (Part 1) — CPAS 3

Learn how to secure your web applications and their production environments

itnext.io

 

How to implement csrf protection on a JWT-based app (Node, csurf , Angular)

I have been developing an application in Node.js and Angular that uses JWT for authentication and authorization. The authentication token…

david-silva.medium.com

 

[참고] postman으로 csrf 토큰 테스트하기

 

Automatically Set CSRF Token in Postman — Django Tips

Django has inbuilt CSRF protection mechanism for requests via unsafe methods to prevent Cross Site Request Forgeries. When CSRF protection…

medium.com

 

 

아직 궁금한 점이 있긴한다..

- 해커와 실제 사용자가 동시에 같은계정(사용자계정)으로 접속했을 때 csrf는 진짜 사용자가 누구인지 어떻게 알 수 있을까?

- 해커가 사용자의 아이디와 비밀번호를 알게된다면, 쿠키에는 csrf토큰값이 있을텐데 이게 왜 해커가 사용자인척하는 csrf 공격을 막을 수 있는건지 자료를 찾아봐도 잘모르겠다. 조금 더 찾아보고 분석해볼 필요가 있다 ㅠㅠ

 

그러나 필자가 보기에는 쿠키에서 값을 찾는다 하더라도 파싱한다하더라도 accessToken과 비슷해보였다.

2단계 인증으로 요청클라이언트가 맞는지 직접 클라이언트에게 확인하는 방식이 더 안전한 거같다.

아래 네이버처럼 새로운 환경에서 로그인했다는 것을 메일알림을 받아서 인증하는거처럼 말이다.

그러면 또 궁금한점이 생겼다. "로그인 한 환경/국적/기기를  어떻게 알 수있는걸까?" 

 

 


helmet을 사용해도된다.

 

helmet에도 csrf, xss 등을 대비하는 해킹에 대비할 수 있는 함수들이 있다.

helmet은 node.js 환경에서 많이 사용되는 보안관련 패키지다.

http헤더를 적절히 설정하여 잘 알려진 일부 웹 취약점으로부터 앱을 보호한다.

http 헤더를 설정하는 15개가량의 미들웨어들이 있다.

설치 및 사용방법도 심플하다.

$ npm install helmet --save

 

주로 main함수에서 app.use(helmet()) 한줄만 입력해도 된다.

 

https://www.npmjs.com/package/helmet

 

helmet

help secure Express/Connect apps with various HTTP headers. Latest version: 6.0.1, last published: 2 months ago. Start using helmet in your project by running `npm i helmet`. There are 3542 other projects in the npm registry using helmet.

www.npmjs.com


[참고]

더보기

[CSRF]

https://nordvpn.com/ko/blog/csrf/

 

크로스 사이트 요청 위조(CSRF)의 의미

크로스 사이트 요청 위조란 무엇일까요? 이 글에서 크로스 사이트 요청 위조의 의미와 방지 방법을 확인해 보세요

nordvpn.com

https://medium.com/a-layman/jwt-authentication-in-nestjs-refresh-jwt-with-cookie-based-token-2f6b860f7d67

 

JWT Authentication in NestJS — Refresh JWT with Cookie-based Token

In the previous article, we introduced the implementation of JWT step by step. However, there is still something that can be improved.

medium.com

https://medium.com/a-layman/where-should-we-store-the-jwt-for-spa-memory-cookie-or-localstorage-2491912d8e79

 

Where should we store the JWT for SPA? Memory, Cookie, or LocalStorage?

I develop an SPA application on Django/DWF recently. I used JSON Web Token (JWT) to authorize users for login and other operations. It’s…

medium.com

https://lts0606.tistory.com/627

 

Nestjs 프레임워크 서버(XSS 방지, Cross Site Scripting) -11

# XSS(cross site scripting) 크로스 사이트 스크립트 변조(cross site scripting, xss)는 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해 사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의

lts0606.tistory.com

https://itnext.io/how-to-secure-your-web-applications-part-1-cpas-3-715b72973623

 

How to secure your web applications (Part 1) — CPAS 3

Learn how to secure your web applications and their production environments

itnext.io

 

 

[Access Token의 문제점과 Refresh Token]

https://hudi.blog/refresh-token/

 

Access Token의 문제점과 Refresh Token

Access Token의 문제점 사용자의 잦은 로그아웃 경험 현재 달록에서는 Refresh Token을 사용중이지 않다. Access Token 만을 사용하여 사용자를 인증한다. 현재 달록의 Access Token 유효 기한은 24시간 즉, 하

hudi.blog

 

[npm 패키지 설치 오류 해결방안]

https://velog.io/@yonyas/Fix-the-upstream-dependency-conflict-installing-NPM-packages-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%EA%B8%B0

 

npm install `--force` and `--legacy-peer-deps` 차이점

참고 https://stackoverflow.com/questions/66020820/npm-when-to-use-force-and-legacy-peer-deps

velog.io

 

https://velog.io/@dev_cecy/npm-install-%EC%98%A4%EB%A5%98-code-ERESOLVE

 

npm install 오류 (code ERESOLVE)

예전에 작성했던 코드를 로컬로 다시 클론받아 코드를 수정하려고했다. 화면을 보기위해npm start를 해주었더니, script 오류가 났고🤦🏻‍♀️ 당황하지 않고 npm install을 해주었다. 그랬더니 이

velog.io

 

 

[csrf 구현]

https://portswigger.net/web-security/csrf/bypassing-token-validation

 

Bypassing CSRF token validation | Web Security Academy

In this section, we'll explain what CSRF tokens are, how they protect against CSRF attacks, and how you can potentially bypass these defenses. What is a ...

portswigger.net

https://blog.naver.com/PostView.naver?blogId=sssang97&logNo=221942513392 

 

[Nest.js] CSRF 보안 적용

nest는 기본적으로 이런저런 보안사항들을 기본적으로 제공하진 않기 때문에, 모듈을 설치해서 등록해야만 ...

blog.naver.com

 

https://inpa.tistory.com/entry/NODE-%EB%B3%B4%EC%95%88-%F0%9F%93%9A-csurf-%EB%AA%A8%EB%93%88-%EC%82%AC%EC%9A%A9%EB%B2%95

 

[NODE / 보안] 📚 csurf 모듈 사용법 - CSRF 공격 방지

csurf 모듈 csurf 모듈은 CSRF 공격을 방지하는 보안 모듈이다. csurf 모듈은 CSRF Secret와 CSRF Token을 만들어서 서로 매칭이 되는지 확인하는 기능을 손쉽게 제공하는 식으로, 보통 CSRF Secret는 session/cookie

inpa.tistory.com

 

 

Invalid csrf token with NestJS

I would like to implement Csrf protection with NestJS and Quasar. But I think I misunderstand something... btw I'm not doing SSR, so I don't send the form from the back to the view. Here is the Nes...

stackoverflow.com

 

 

GitHub - pillarjs/understanding-csrf: What are CSRF tokens and how do they work?

What are CSRF tokens and how do they work? Contribute to pillarjs/understanding-csrf development by creating an account on GitHub.

github.com

 

 

How to secure your web applications (Part 1) — CPAS 3

Learn how to secure your web applications and their production environments

itnext.io

 

https://github.com/wafflestudio/seminar-2020/issues/108

 

(옮김) HTTP는 크게 Header와 Body로 이루어지는데, Postman의 response를 보면 왜 Cookies가 따로 있나요? ·

이번 세미나부터는 세미나 이후 참여가 자유인 질의응답 시간을 따로 가집니다. 물론 개인 일정, 다음 세미나 등으로 참여가 어려운 분이 있을 수 있습니다. 이 내용은 오늘 Backend 세미나 이후

github.com

 

 

728x90
반응형