Post

XSS / CSRF

서버에서 받아온 데이터를 그냥 innerHTML로 할당하는 것은 지양해야 한다.

XSS

CSRF

  • CSRF의 핵심은 “해당 스크립트를 실행한 클라이언트의 세션으로 서버에 요청한다” 이다.
  • 스크립트를 실행하는 클라이언트의 쿠키, 세션, 권한으로 서버에 요청.

브라우저가 페이지를 파싱하다 <img src="URL">를 만나면 서버에 해당 URL을 요청하게 되는데, 원래 페이지에 대한 요청과 이 요청 사이의 차이점은 URL이 다르다는 것 뿐이다. 즉, img tag 에 지정된 request도 동일하게 처리한다.

GET method를 사용하는 경우 url로 파라미터를 넘길 수 있기 때문에 src attribute에 파라미터를 포함한 url을 적는 방법이 많이 쓰이며 이를 transclude라고 한다.

실제 악성파일을 분석하며 가장 흔하게 봤던 유형은 이미지 내에 삽입된 iframe이었고 대체로 일단 컨트롤 할 수 있는 악성 사이트로 redirect 시키는 방법이 사용되었다. 그래야 헤더 등등을 조작할 수 있으니까.

공격자가 다음과 같은 코드를 미리 작성해 놓으면, 코드를 파싱하는 victim은 서버에 펜 50개를 구매하겠다는 request를 보내게 된다.

1
2
<img src="http://store.example.org/buy.php?item=pen&quantity=50" />

공격자의 의도 대로 victim의 권한으로 서버에 요청하는 것을 막으려면 token을 발급하고, client에서 request 시 token 포함하도록 구성한다. 그리고, GET이 아니라POST 를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
session\_start();
$token = md5(uniqid(rand(), TRUE));
$\_SESSION['token'] = $token;
$\_SESSION['token\_time'] = time();
?>

  

<form action="buy.php" method="POST">
<input type="hidden" name="token" value="<?= $token?>"/>

...
</form>

* pw hash가 아니기 때문에 md5를 사용해도 상관 없다. pw hash의 경우는 안전한 hash algorithm에 salt도 추가해서 사용해야 한다.

근데 어차피 token은 서버에 저장되는건데, 굳이 <?= $token?>으로 client에 보낸 다음 다시 hidden으로 이를 받을 필요가 있나 싶지만토큰을 단순히 서버에서 가지고만 있는 것은 아무 소용이 없다.

중요한 것은 client가 전송하는 요청이 공격자가미리 만들어 놓은 위조된 요청 인지 아닌지를 확인하는 것이다. token은 각 사용자마다 다르게 발급되기 때문에 공격자가 미리 만들어 놓을 수는 없다.

1
2
3
4
5
6
if (isset($\_SESSION['token'] &&
($\_POST['token'] == $\_SESSION['token']) &&
(time() - $\_SESSION['token\_time']) <= 300) {
....
}

This post is licensed under CC BY 4.0 by the author.