이번 시간에는 새로운 웹 해킹 기법을 소개하겠습니다.
CSRF (Cross Site Request Forgery)
CSRF는 요청을 위조한다는 의미를 가집니다.
요청을 위조한다? 이해를 할때 클라이언트가 서버로 요청을 하게 만드는 것이라고 생각하면 됩니다.
그럼 어떻게 서버로 요청을 하게 만들까요?
우리는 XSS 공격을 배울 때 원하는 스크립트를 실행하게 만든 링크를 만들고 링크에 접속하면 해당 스크립트가 실행되었습니다.
이것처럼 원하는 요청을 링크로 만들어 해당 링크에 접속하면 서버로 요청을 보내게하는 것입니다.
비밀번호를 변경하는 페이지가 있습니다. update를 누르면 비밀번호가 변경됩니다.
비밀번호 변경이 어떻게 이루어지는지 버프로 확인해보겠습니다.
post 메서드를 통해 pw에 값을 받아 해당 비밀번호로 변경해주고 있습니다.
우리는 링크를 접속해서 요청을 보내려고 하기 때문에 get 메서드로도 요청이 정상적으로 이뤄지는지 확인해보겠습니다.
get으로도 비밀번호가 변경되는 것을 확인할 수 있습니다. 그럼!!! 해당 요청을 보내는 링크를 만들어 접속하면 비밀번호가 변경될까요?
비밀번호를 바꾸기 위해 1111로 변경해보겠습니다.
원해 비밀번호였던 1234가 아닌 1111로 입력해야 로그인이 성공합니다.
즉, 링크 접속으로 요청을 보냈기 때문에 비밀번호를 변경할 수 있었습니다.
만약 피해자에게 링크를 접속하게하면 원하는 비밀번호로 변경시킬 수도 있을 것입니다.
이렇게 서버로 요청을 보내게 하는것!! 이 CSRF입니다.
CSRF vs XSS
CSRF | XSS | |
차이점 | 피해자가 서버로 임의의 요청을 보내게하는 공격 | 스크립트를 삽입해 피해자측에서 실행시키는 공격 |
공통점 | 클라이언트를 대상으로 하는 클라이언트 측 공격 |
앞에서 본 CSRF는 피해자의 조작이 필요하지만 XSS 취약점을 만나면 임의의 요청을 보내게 하는 것을 스크립트 실행으로 할 수 있기 때문에 피해자의 조작없이도 공격자가 CSRF 공격(서버로 임의의 요청을 보내기)을 할 수 있습니다.
예를 들어 <img src="CSRF 공격 주소"> 를 작성하면 해당 링크로 GET 요청을 보낼 수 있습니다.
그렇기 때문에 CSRF 공격을 XSS 와 함께 사용하는 경우가 많아 CSRF 공격을 XSS 로 착각할 수 있기때문에 확실하게 CSRF는 서버로 임의의 요청을 보내게 하는 공격!! XSS 는 클라이언트 측 스크립트를 삽입해 실행시키는 공격!! 이라는 차이를 알아야합니다.
XSS 취약점이 발생하면 쿠키 탈취, 정보 탈취 처럼 CSRF공격은 XSS 취약점 발생 시 사용할 수 있는 공격 기법 중에 하나이기도 합니다.
CSRF 공격이 무엇인지 간단하게 알아보았습니다.
그럼 링크를 통해 공격하는 것이니 GET 요청에서만 일어날 수 있는 것인가?? 아닙니다!!
CSRF가 일어나는 이유는 요청을 위조하기 때문입니다. 즉, 요청에 대한 인증이 제대로 이루어지지 않기때문입니다.
위의 비밀번호 변경을 예시로 들어보겠습니다.
우리가 보통 비밀번호 변경을 할 때 이전 비밀번호를 같이 입력합니다. 이전 비밀번호를 입력 받아 비밀번호 변경을 처리한다면 우리가 만든 링크 접속만으로는 비밀번호 변경을 하지 못할 것입니다. 우리가 만든 링크에는 이전 비밀번호를 포함하지 않기때문이죠.
이렇게 인증을 해주어야 CSRF를 막을 수 있는 것입니다. 그렇기 때문에 GET 요청 뿐만 아니라 인증을 제대로 하지 않는 모든 요청에서 발생할 수 있습니다.
그럼 POST 요청 시에는 어떻게 공격을 할 수 있을까요?
POST 요청은 form 태그에 들어있는 정보를 보냅니다. 우리는 form태그를 만들어 원하는 정보로 채운뒤 요청을 보내는 것입니다. 물론 form태그를 작성해야하기 때문에 XSS 공격과 함께 이루어져야 합니다.
위의 예시에서 사용한 비밀번호 변경입니다. 원해 post를 이용해 요청을 처리했기 때문에 사용해보겠습니다.
// post 요청을 보내는 form태그
<form method="post" action="http://ctf.segfaulthub.com:7575/csrf_1/mypage_update.php">
// pw=1234
<input type="text" name="pw" value="1234"/>
// 요청을 보내는 버튼
<button type="submit">Click Me</button>
</form>
위와 같은 코드 form 태그를 사용하면 예시와 같은 요청을 보낼 수 있습니다.
게시글에서 XSS 취약점이 발생해 위 코드와 똑같이 작성해보니 사진과 같이 form 태그가 만들어진 것을 확일할 수 있습니다.
버튼을 클릭하면 우리가 생각한 것처럼 비밀번호가 변경됩니다.
하지만!! 이것은 버튼을 클릭해야지만 비밀번호가 변경됩니다. 누가봐도 수상한 버튼을 클릭하진 않을 것입니다. 자동으로 요청을 보낼 수 있으면 좋을 것같습니다.
<form id="update" method="post" action="http://ctf.segfaulthub.com:7575/csrf_1/mypage_update.php">
// hidden 타입으로 input 태그 숨김
<input type="hidden" name="pw" value="1234"/>
</form>
<script>
// 스크립트를 이용해 자동으로 요청
document.getElementById('update').submit();
</script>
이때 submit()함수를 사용하면 해당 form태그로 요청을 보낼 수 있습니다.
게시글 확인만으로도 비밀번호를 변경할 수 있습니다.
이것도 alert함수 때문에 비밀번호가 변경된 것을 피해자는 바로 확인할 수 있습니다.
갑자기 get을 사용한 것이 이상하지만 현재 상황에서 alert를 무시하기 위해서 사용했습니다....
여기에 위에 설명한 img 태그로 get요청을 보내는 방식을 사용하니 회원정보가 수정됐다는 경고창이 뜨지 않습니다.
사진이 load되진 않았지만 뭐야??? 하며 그냥 지나칠 수 있을 것입니다. 하지만 뒤에서는 get으로 비밀번호가 변경되는 요청을 보내고 있는 것입니다.
뒤에서 post요청 시 alert 무시까지 해보겠습니다.
다른 예시로 비밀번호 변경 후 다시 로그인 페이지로 이동시킨다면 비밀번호 요청 후 페이지가 바뀌게 되어 피해자는 게시글을 읽었는데 로그인페이지로 이동하면 이상하다고 느낄 것입니다.
이때 사용할 수 있는 것이 iframe 태그 입니다.
iframe 태그는 저번 시간에도 했던 것처럼 다른 페이지를 그대로 가져와 출력해줍니다.
또한 form태그의 target속성과 iframe name속성으로 연결시켜 iframe내에서 form을 처리할 수 있습니다.
그렇기 때문에 iframe안에서 비밀번호 요청을 보내어 성공 후 리디렉션 하는 것을 iframe 안에서 실시하며 실제로 접속한 페이지는 바뀌지 않게하여 피해자는 모르게 하는 것입니다.
// form과 연결하여 iframe 생성
<iframe name="test"></iframe>
// post 요청 데이터 작성
<form id="hack" method="post" action="http://ctf.segfaulthub.com:7575/csrf_2/mypage_update.php" target="test">
<input type="hidden" name="pw" value="1111">
</form>
// post 요청
<script>
document.getElementById('hack').submit();
</script>
게시글을 읽으니 iframe 내에서 비밀번호 변경 요청을 하고 리디렉트를 태그내에서 실시하는 것을 확인할 수 있습니다.
이제 style="display: none" 속성을 더해서 iframe을 화면에서 안보이게 한다면 피해자는 아무것도 모르고 비밀번호가 변경될 것입니다.
그리고 사실 위에 응답을 보면 alert로 비밀번호 변경을 경고창에 띄워주는 것을 확인할 수 있습니다. 방금 실습에서는 일부로 제가 버프스위트로 응답에서 지워버려 안 떴지만, alert는 iframe 내에서 실행할 수 없기때문에 응답이 오면 화면에 바로 띄워버립니다.
그럼 바로 알아차리겠죠??? 이것도 우회 방법이 있습니다.
원래 페이지대로 작동하면 게시글을 확인하면 사진과 같이 회원 정보 수정 경고창이 뜹니다.
이때 iframe 의 sandbox 속성을 사용하여 스크립트 실행을 막아버리는 것입니다.
(비어 놓음) | 모든 제한 사항(restrictions)을 적용함. |
allow-forms | 리소스(resource)가 폼 데이터를 제출할 수 있도록 허용함. |
allow-modals | 리소스가 모달 윈도우(modal window)를 열 수 있도록 허용함. |
allow-orientation-lock | 리소스가 화면 방향 전환을 잠글 수 있도록 허용함. |
allow-pointer-lock | 리소스가 Pointer Lock API를 사용할 수 있도록 허용함. |
allow-popups | window.open()이나 target=“_blank”, showModalDialog() 등의 팝업(popup)을 허용함. |
allow-popups-to-escape-sandbox | 모든 제한 사항이 적용된 문서(sandboxed document)에서 새로운 창(window)을 열 때 제한 사항을 상속받지 않은 창을 열 수 있도록 허용함. |
allow-presentation | 리소스가 프레젠테이션 세션(presentation section)을 시작할 수 있도록 허용함. |
allow-same-origin | 리소스가 same-origin policy를 통과된 것처럼 취급될 수 있도록 허용함. |
allow-scripts | 리소스가 스크립트를 실행할 수 있도록 허용하지만, 팝업창은 생성하지 못함. |
allow-storage-access-by-user-activation | 리소스가 Storage Access API를 사용하여 상위 스토리지 기능에 접근 요청을 할 수 있도록 허용함. |
allow-top-navigation | 리소스가 최상위 브라우징 컨텍스트(_top)를 탐색할 수 있도록 허용함. |
allow-top-navigation-by-user-activation | 리소스가 사용자의 요청이 있을 때만 최상위 브라우징 컨텍스트(_top)를 탐색할 수 있도록 허용함. |
위와 같은 값으로 iframe에 제약조건을 걸거나 허용할 수 있습니다.
속성 중 alert에 관한 것이 allow-modals 제어입니다. 모달 윈도우 허용 막아야 응답에 대한 반응을 안하기 때문에 allow만 안적어주면 됩니다. 하지만 sandbox="" 를 적어주면 모든 허용에 대해 막기 때문에 sandbox 속성만 적어주면 됩니다.
<iframe name="test2" style="display: none;" sandbox="allow-forms"></iframe>
<form id="hack" method="post" action="http://ctf.segfaulthub.com:7575/csrf_2/mypage_update.php" target="test2">
<input type="hidden" name="pw" value="hacking">
</form>
<script>
document.getElementById("hack").submit();
</script>
allow-forms를 해주어야 form 요청을 할 수 있는 줄 알았는데 요청은 iframe 내에서 하는 것이 iframe 부모인 게시글에서 실행하는 거라 상관이 없었습니다.
게시글을 확인하니 회원정보 변경에 대해 알려주지 않습니다. 하지만 뒤에서는 비밀번호 변경이 이뤄지고 있습니다.
바꾼 비밀번호로 로그인하니 성공합니다. 이렇게 CSRF 공격이 이뤄지는 모습들을 전체적으로 확인했습니다.
공격자가 피해자가 모르게 요청을 보내게 하기위해 여러가지를 알아보았는데
결론은 비밀번호 변경뿐만 아니라 서버로 어떠한 요청을 보내게 하는 것이 CSRF 공격이라고 할 수 있습니다.
'웹 해킹' 카테고리의 다른 글
웹 해킹 공부 일기장 10 - 1 (File Upload 취약점) (0) | 2024.02.08 |
---|---|
웹 해킹 공부 일기장 9 - 1 (CSRF 정리) (0) | 2024.02.01 |
웹 해킹 공부 일기장 7 - 과제2 (XSS) (0) | 2024.01.15 |
웹 해킹 공부 일기장 7-과제1 (XSS) (0) | 2024.01.14 |
웹 해킹 공부 일기장 (자바스크립트) (0) | 2024.01.12 |