CSRF 공격

코드깎는 노인·2019년 12월 26일
0

보안

목록 보기
1/2

CSRF attack(Cross Site Request Forgery)은 웹 어플리케이션 취약점 중 하나로 인터넷 사용자(희생자)가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격이다.이를 예방하기 위해 매 요청마다 서버로 토큰을 이용한 인증을 해줘야 한다

공격방식은 다음과 같다
1.사용자가 브라우저에 로그인해있다(유효한 쿠기보유)
2.사용자가 공격용 URL이 img의 src 속성값으로 박혀있는 페이지에 접근
3.사용자의 인증정보(쿠키)를 사용한 스크립트가 실행
4.서버는 공격명령을 사용자의 요청으로 인식하고 실행

방어

웹브라우저의 Same Origin 정책으로 공격자가 쿠키값에는 접근할 수 없는것을 이용하여
1.브라우저는 get요청으로 토큰값과 _csrf(시크릿키)값을 서버로 부터 받는다
2.브라우저에서 write요청시 header에 토큰값을 주고 쿠키값에 시크릿키를 부여하여 서버의 미들웨어에서 토큰값을 decode해서 decode한 시크릿키가 쿠키값과 일치하는지 체크한다

다음은 csurf 미들웨어를 사용한 Double-Submit Cookie Pattern의 예시이다

var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var bodyParser = require('body-parser')
var express = require('express')

// setup route middlewares
var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })

// create express app
var app = express()

// parse cookies
// we need this because "cookie" is true in csrfProtection
app.use(cookieParser())

app.get('/form', csrfProtection, function (req, res) {
  // pass the csrfToken to the view
  res.render('send', { csrfToken: req.csrfToken() })
})

app.post('/process', parseForm, csrfProtection, function (req, res) {
  res.send('data is being processed')
})
fetch('/process', {
  credentials: 'same-origin', // <-- includes cookies in the request
  headers: {
    'CSRF-Token': token // <-- is the csrf token as a header
  },
  method: 'POST',
  body: {
    favoriteColor: 'blue'
  }
})

get요청시 서버는 토큰과 시크릿기값을 발급하여 브라우저로 넘겨주고 브라우저는 post요청시 header에 토큰값을,쿠키에 시크릿키값을 삽입하여 보내면 서버는 csrfProtection미들웨어를 통해 유효한 토큰인지 검증한다.

주의할 점은 쿠키값에 시크릿키값이 제대로 들어가냐는 점이다

cookie:
'_csrf=hSV3aZYkhRsa9USOPQg3IGkm; connect.sid=s%3AB8anx27UD2uosXEEF0oG43-ZjZnNrFtt.CqDnYCAbfm7Qw%2Br09uj%2BlMssb68ynFwTtyzNTwHpC9E; XSRF-TOKEN=BUrDmnrj-0i_l211cbB9i5pP-h_Gxp4kQ06Q',

1

cookie:
   'XSRF-TOKEN=K832IHRZ-Tyobtw-kwSeGYQpDJr-uE9HXffU; token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IngiLCJpYXQiOjE1Nzc0MjcxMzN9.eIWMKK_Z7aE4vn8dcPZX8EEJ0mpaLLcWSoyyl5OCTpc; connect.sid=s%3ALdu-bgwa5jX6-dEvE59ACNDwRJLOwPsV.dUMZPck96IK2KrvXBDm9%2BQZnXwsqH3tLjW01sBun50w' }

2

1번과 2번은 서버에서 req.headers의 쿠키값인데 1번과 같이 _csrf시크릿키값이 들어올경우 valid하고 없는경우 invalid token error가 발생한다.

same-origin-policy로 인해 다른 도메인으로 부터 쿠키값에 접근할 수는 없지만 이는 완전하지않다.
서브도메인을 이용하여 쿠키값을 조작할 수 있다.
예를들어 https://www.example.com의 서브도메인 https://www.example.com/submit에서
<script>document.cookie = “_csrf=a; Path=/submit; domain=example.com”;</script> 과같은 xss공격 스크립트를 이용하거나
<meta http-equiv="set-cookie" content="_csrf=a; Path=/submit; domain=example.com"> 과 같이 메타태그를 이용하여 쿠키값을 조작할 수 있다.

이를 예방하기 위해 https로 사이트를 구축하고 HSTS헤더값을 설정하여 모든 서브도메인에 적용시켜야 한다

profile
내가 볼려고 만든 블로그

0개의 댓글