WriteUp

webhacking.kr stored xss vuln

webhacking.kr의 48번 문제 (http://webhacking.kr/challenge/bonus/bonus-12/ ) 는 파일 삭제 과정에서
불충분한 유저 입력 검증으로 인한 OS command injection 을 다루는 문제입니다.
해당 문제 내에서 “운영자가 의도하지 않은 취약점을 이용한 Stored XSS 공격”이 가능합니다.

  • get index.php’s source code

문제 내에서 파일을 업로드하고 코멘트를 달게되면 자동으로 아이콘이 추가됩니다.

해당 아이콘은 닉네임의 길이에 따라서 3.jpg, 4.jpg, 5.jpg 등의 이름을 가지게 됩니다.
그런데 여기서 1.jpg에 접근을 해보면 파일이 깨져 있습니다.

감이온다 감이…!
view-source: 를 해보면…


해당 디렉토리 내의 모든 파일이 담겨있고…
그중에는 index.php의 소스코드도 있습니다.


획득한 index.php의 소스코드는 다음과 같습니다.

이 시점에서 뭐야 장난하냐 이걸 어떻게 알아! 라고 하실 수 있지만…
이건 CTF 챌린지가 아닌 리얼월드에서 터진 버그입니다 🙂

그럼 대체 왜 이러한 파일이 생겼는지 생각해봅시다.
왜 하필이면 1.jpg 일까요?
보통 bash상에서 * 로 파일을 지칭할 때 숫자 -> 알파벳순 으로 파일을 정렬합니다.
운영자님이 파일을 백업할 일이 생겨 tar로 묶을 때 tar -cvf * 이런식으로 실수를 했다면?
디렉토리에서 가장 앞에 있는 1.jpg 를 제외한 나머지 파일들을 묶어 1.jpg에 write하게 됩니다.
ls -al을 친 후 파일 크기가 변한걸 유심히 보지 않는 이상 1.jpg라는 폭탄이 생긴걸 눈치채긴 어렵죠.
리얼월드에서도 관리자의 실수로 인해 충분히 발생할 수 있는 취약점이지만… 점검하기는 쉽지는 않겠지요.
아무튼 이렇게 index.php의 소스코드를 획득했습니다!

  • SQL Injection

이 챌린지의 원래 미션이였던 OS command injection은 ;ls 라는 문자열이 하드코딩되어있어(21라인) 악용이 불가능합니다.
이 파일에서 터질만한 취약점은 SQL Injection 말고는 안보이는군요.
memo를 작성할때(34라인) 만 escape를 해주고 출력할때는 escape를 하지 않기에 49라인에서 Insert SQL Injection을 성공하면
Stored XSS까지 악용이 가능해보입니다.

이제 49라인을 뜯어봅시다.
$_SESSION[id], $tm, $f, $_POST[memo] 총 4개의 변수가 쿼리문에 동적으로 박히며,
$tm 변수(36라인)를 제외하고는 모두 우리가 조작이 가능한 값입니다.
트리거하기에 아주 적합하죠.

먼저 $f 변수입니다.
우리가 업로드한 파일의 원래 이름을 변수명으로 담은 후(32라인) 3글자를 넘는지 체크(40라인)합니다.
그 후에… 오 맙소사 아무런 필터링이 없군요.
webhacking.kr은 magic_quotes_gpc=on 설정이지만, $_FILES 변수는 magic_quotes_gpc의 영향을 받지 않습니다.
우리는 그냥 파일네임을 \ 로 설정해 쿼리의 문법을 망가트린 후에 $_POST[memo] 변수에 ,1),(1,2,3,4)# 라는 식으로 공격을 하면 끝입니다.
그리고 싱글벙글하며 페이로드를 날려보면… 공격에 실패함을 알 수 있습니다.
소스코드와 설정을 모두 고려해보면 성공할 수 밖에 없는 페이로드인데 실패했으니…
운영자님이 1.jpg를 만든 후에 index.php의 소스코드를 추가적으로 변경했다고밖에 생각할 수 없군요.
$f 변수를 사용한 공격은 불가능합니다.
소스코드와는 다르게 필터링이 되어있습니다.
억울하지만 다른 변수를 찾아봅시다.

$_POST[memo] 변수를 사용해 쿼리를 망가트리는건… magic_quotes_gpc=on 설정이니 불가능합니다.
그럼 남은건 $_SESSION[id] 변수네요.
사실 해당 변수를 사용해 공격하는 제로데이를 제가 이미 블로그에 포스팅한적이 있습니다.
해당 포스팅의 핵심은… asdf’ 라는 아이디로 회원가입, 로그인을 하면 $_SESSION[id] 변수에 asdf’ 라는 스트링이 그대로 박혀
세션 아이디를 사용하는 챌린지 내에서 Indirect SQL Injection이 가능하다는 것입니다.
그럼 우리는 rubiya’#이라는 아이디로 회원가입, 로그인을 한 후 $_POST[memo] 에 %0a 를 사용해 중간의 쿼리를 주석으로 처리해주고
그 후에 쿼리조작을 하면 됩니다.
$_POST[memo] 에 실제로 넣는 값은…
%0a,999999999999,0×41,0x3c7363726970743e616c6572742831293c2f7363726970743e)#(<script>alert(1)</script>의 hex값) 입니다.

이렇게 해서 webhacking.kr 48번 stored xss 성공입니다!

  • 덧붙여…

사석에서 자주 하는말이지만 webhacking.kr 에는 아직 패치되지 않은 취약점이 5개 이상 존재합니다.
또한 wechall.net 에 등록된 워게임 중 10개 이상의 워게임이 취약점을 가지고 있습니다.
취약점을 찾다보면 해커인 개발자가 어떻게 해커로부터 자신의 사이트를 방어를 했는지, 그 사고의 흐름을 따라가는게 아주 재미있더라구요.
여러분도 워게임 사이트 자체의 취약점을 찾아보시는건 어떤가요?

Leave a Reply

Your email address will not be published. Required fields are marked *