본 내용은 http://bananapayload.org에 본인이 작성했던 내용임.


WEB 200 (한승현 사이트 문제 이름이 생각이 안남)


사이트를 접속하면http://211.58.255.64:8078/webprob/index.php?p다음과 같은 URL을 포한하고 있으며딱 URL이 include 취약점을 점검해보라 알려주고 있다. p라는 인자를 변경할 경우 오류와 함께 실제파일의 경로를 확인할 수 있다.

 

include를 수행하는 파일명의 경우 inc이기 때문에 모두 다운받을 수 있었다다운로드 받은 소스코드를 분석한 결과 다음과 같은 문제점이 존재했다.

 

로그인 성공 시 serialize를 통한 세션 생성 (loginproc.inc)

$_SESSION['memdata'] = mb_convert_encoding(serialize(mysql_fetch_array($result, MYSQL_ASSOC)), "ASCII", "UTF-8");

 

2. 세션정보 확인 시 unserialize를 통한 세션값 추출 (tohsy.inc)

$rowm = unserialize($_SESSION['memdata']);

 

저장할 때 UTF-8을 아스키로 인코딩을 하고실제 unserialize 할 때는 디코딩이 수행되지 않는다이를 확인하기 위해실제 코드를 작성하여 유니코드(한글)을 입력한 결과,한글 1글자가 유니코드에서는 3바이트로(원래 2바이트인줄알았는데..)로 들어가지만인코딩 때문에 1글자로 변하는 것을 확인할 수 있다때문에 unserialize에서 오류가 발생하고이를 이용하여 공격 수행이 가능하다는 것을 확인했다.

 

친절하게도 tohsy.inc에서는 오류가 있을 경우 덤프를 해준다이걸 보고도 쉽게 문제 의도의 유추가 가능하지만 머리가 나쁜지 초반에 이를 확인하진 못했다.

 

한글로 가입을 할 경우 tohsy.inc에서 덤프를 확인할 수 있으며 다음과 같은 결과를 출력한다한글 2글자로 가입한 결과 다음과 같은 결과를 덤프 해준다.

 

a:4:{s:3:"idx";s:4:"1234";s:2:"id";s:6:"??";s:2:"pw";s:1:"1";s:5:"level";s:1:"1“}

 

입력 가능한 값인 id와 pass를 통해 데이터의 조작이 가능하다는 것을 확인하였고 다음과 같은 코드 구성을 통해 공격을 수행하였다.

 

8글자의 한글 id를 통해 가입할 경우 24-8 = 16 바이트의 데이터를 덮을 수 있어입력한 암호를 통해 serialize된 구조의 구성이 가능하다.

 

a:4:{s:3:"idx";s:4:"1234";s:2:"id";s:24:"????????";s:2:"pw";s:YY:"XXXXXXXXXXXXXXXXX“";s:5:"level";s:1:"1“}

 

array의 크기가 4이기 때문에 기존 2개의 데이터를 제외하고 추가적으로 두 개의 데이터의 추가 및 변경이 가능하다.

 

본 문제에서는 다음과 같은 조건을 통해 비밀글을 보여준다.

 

세션이 재대로 unserialize가 되는가.

세션에 포함된 idx, level에 해당하는 사용자가 존재 하는가.

세션의 id와 디비상의 id가 같은가.

level값이 2거나세션의 idx와 글쓴이의 idx가 같은가

 

 

위 조건을 성립하기 위해선, idx, level 값을 조작하여디비에서 글쓴이의 계정정보를 읽어오도록 수행한 후, id를 조작하여 디비의 id와 맞춰주면 된다하지만 이 문제를 해결하기 위해서는 3개의 값의 조작이 필요하다.

 

$result = mysql_query("SELECT id FROM member WHERE idx=$rowm[idx] and level=$rowm[level]");

이를 해결하기 위해 다음 쿼리에 값 조회시 쿼터를 사용하지 않는 것을 확인하였으며, level 값에 sql injection 쿼리를 주입했다가입 시 필터링에 포함된 각종 주석 및 공백 필터를 우회하기 위해, TAB(0x09)값을 사용하였다. (Paros를 통해 전달 시 조작)

 

또한 추가적으로 id값을 비밀글의 계정인 readme로 변경을 수행하였다. (디비 첫 번째 값이 readme 계정)

 

마지막으로 level값을 2로 맞춰줘야 하는데, php에서는 숫자 문자열” 이렇게 될 경우 앞의 숫자만을 인식하기 때문에 우회하는데 큰 어려움이 없었다최종적으로 다음과 같은 id, pw값으로 가입할 경우 tohsy 페이지에서 인증키의 확인이 가능하다.

 

ID : 8글자 한글

PASS : ;s:2:"id";s:6:“readme”;s:5:"level";s:8:"2 or 1=1“}

 

위의 공백은 paros를 통해 전송시 tab(0x09)로 조작하였으며비밀글을 확인하여 킷값을 확인할 수 있었다

'Hacking > Write up' 카테고리의 다른 글

화이트햇 콘테스트 웹(200) 문제 풀이  (0) 2013.11.05
hdcon2012 stage2-1  (0) 2013.11.05
Posted by EXSO

댓글을 달아 주세요