OverTheWire Bandit


Contents:



The following are (brief) notes/solutions to the overthewire bandit CTF. I've played it last year or so, but I thought it'd be a good time to try again and document it this time.

While this is a beginner CTF, it requires some Linux knowledge. If you don't know much about Linux, I recommend you go through the Linux Journey.

0->1

Connect to the gameserver. You might want to know why I pass -o PreferredAuthentication=password.

ssh -o PreferredAuthentications=password bandit0@bandit.labs.overthewire.org -p 2220
bandit0@bandit:~$ cat readme
Congratulations on your first steps into the bandit game!!
Please make sure you have read the rules at https://overthewire.org/rules/
If you are following a course, workshop, walkthrough or other educational activity,
please inform the instructor about the rules as well and encourage them to
contribute to the OverTheWire community so we can keep these games free!

The password you are looking for is: ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If

1->2

bandit1@bandit:~$ cat ./-
263JGJPfgU6LtdEvgfWU1XP5yac29mFx

2->3

bandit2@bandit:~$ cat "spaces in this filename" 
MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx

3->4

bandit3@bandit:~$ cd inhere/
bandit3@bandit:~/inhere$ ls -lha
total 12K
drwxr-xr-x 2 root    root    4.0K Sep 19 07:08 .
drwxr-xr-x 3 root    root    4.0K Sep 19 07:08 ..
-rw-r----- 1 bandit4 bandit3   33 Sep 19 07:08 ...Hiding-From-You
bandit3@bandit:~/inhere$ cat '...Hiding-From-You' 
2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ

4->5

bandit4@bandit:~$ cd inhere/
bandit4@bandit:~/inhere$ tail ./-file*
==> ./-file00 <==
p&y,(jo.at:uf^@
==> ./-file01 <==
iR,Λ:Y?%AB
==> ./-file02 <==
3       )Æ®#Y-6cIR-$:
==> ./-file03 <==
/
 qGi,2Yb
d
==> ./-file04 <==
rOxh0~ey
c~hnG1
==> ./-file05 <==
}W>#lkdyE
==> ./-file06 <==
60]\$1%o@b/
==> ./-file07 <==
4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw

==> ./-file08 <==
nS
<]
We˥mOD
==> ./-file09 <==
2g?`>5HYAu8g`0$`bandit4@bandit:~/inhere$ 

Only -file07 contains valid flag.

5->6

bandit5@bandit:~$ man find
bandit5@bandit:~$ find inhere/ -type f -size 1033c
inhere/maybehere07/.file2
bandit5@bandit:~$ cat inhere/maybehere07/.file2
HWasnPhtq9AVKe0dmk45nxy20cvUa6EG
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        bandit5@bandit:~$ 

6->7

bandit6@bandit:~$ find / -size 33c -user bandit7 -group bandit6
...
/var/lib/dpkg/info/bandit7.password
...
bandit6@bandit:~$ cat /var/lib/dpkg/info/bandit7.password
morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj

7->8

bandit7@bandit:~$ ls
data.txt
bandit7@bandit:~$ wc -c data.txt 
4184396 data.txt
bandit7@bandit:~$ cat data.txt | grep millionth
millionth       dfwvzFQi4mU0wfNbFOe9RoWskMLg7eEc
bandit7@bandit:~$ 

8->9

bandit8@bandit:~$ sort data.txt | uniq -u
4CKMh1JI91bUIZZPXDqGanal4xvAg0JM
bandit8@bandit:~$ 

9->10

bandit9@bandit:~$ strings data.txt | grep '=='
}========== the
3JprD========== passwordi
~fDV3========== is
D9========== FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey
bandit9@bandit:~$ 

Only FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey is a valid flag.

10->11

bandit10@bandit:~$ base64 -d data.txt 
The password is dtR173fZKb0RRsDFSGsg2RWnpNVj3qRr
bandit10@bandit:~$ 

11->12

bandit11@bandit:~$ cat data.txt | tr "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"
The password is 7x16WNeHIi5YkIhWsfFIqoognUTyj9Q4

12->13

This level felt like one of those deeply-nested Russian dolls...

bandit12@bandit:~$ mktemp -d
/tmp/tmp.lQkfQ4Meus
bandit12@bandit:~$ cp data.txt /tmp/tmp.lQkfQ4Meus/data.txt
bandit12@bandit:~$ cd /tmp/tmp.lQkfQ4Meus/
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ xxd -r data.txt > unhex1
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat unhex1 | gzip -d > f2                                                                                                                                                                                                                      
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file f2
f2: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat f2 | bzip2 -d > f3
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file f3
f3: gzip compressed data, was "data4.bin", last modified: Thu Sep 19 07:08:15 2024, max compression, from Unix, original size modulo 2^32 20480
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat f3 | gzip -d > f4                                                                                                      
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file f4
f4: POSIX tar archive (GNU)
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ tar -xvf f4
data5.bin
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file data5.bin 
data5.bin: POSIX tar archive (GNU)
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ tar -xvf data5.bin
data6.bin
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file data6.bin 
data6.bin: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat data6.bin | bzip2 -d > f7
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file f7
f7: POSIX tar archive (GNU)
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ tar -xvf f7 
data8.bin
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", last modified: Thu Sep 19 07:08:15 2024, max compression, from Unix, original size modulo 2^32 49
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat data8.bin | gzip -d > f9
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ file f9
f9: ASCII text
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cat f9
The password is FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn
bandit12@bandit:/tmp/tmp.lQkfQ4Meus$ cd ..
bandit12@bandit:/tmp$ rm -rf tmp.lQkfQ4Meus

13->14

bandit13@bandit:~$ ssh -i sshkey.private bandit14@localhost -p 2220
bandit14@bandit:~$ cat /etc/bandit_pass/bandit14
MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS

14->15

bandit14@bandit:~$ nc localhost 30000
MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS
Correct!
8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo

Might also be able to get password if the string comparison is susceptible to a timing side-channel. Not tried though.

15->16

bandit15@bandit:~$ openssl s_client localhost:30001
CONNECTED(00000003)
...
read R BLOCK
8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo
Correct!
kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx

closed
bandit15@bandit:~$ 

16->17

bandit16@bandit:~$ nmap localhost -p31000-32000
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-31 15:43 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00011s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT      STATE SERVICE
31046/tcp open  unknown
31518/tcp open  unknown
31691/tcp open  unknown
31790/tcp open  unknown
31960/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

I tried -A to figure out if a port speaks TLS, but it took too long. Instead, I decided to just manually try to connect to each port.

Only 31518 and 31790 respond to openssl s_client localhost:<port>.

For both I get

---
read R BLOCK
kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx
KEYUPDATE
closed

Following the hint, I read the CONNECTED COMMANDS section of man openssl-s_client. There it names two flags: -quiet and -ign_eof. I chose the second one after googling a bit.

Only for openssl s_client -ign_eof localhost:31790 it worked:

...
read R BLOCK
kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx
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-----

closed

Copy the key to your machine, then chmod 400 level17-sshkey.priv, then log in to next level with:

ssh -i level17-sshkey.priv -o IdentitiesOnly=yes bandit17@bandit.labs.overthewire.org -p 2220

17->18

bandit17@bandit:~$ diff *
42c42
< x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO
---
> ktfgBvpMzWKR5ENj26IbLGSblgUG9CzB

The first one turns out to be the correct one.

18->19

$ ssh -p 2220  -o PreferredAuthentications=password bandit18@bandit.labs.overthewire.org cat readme
...
bandit18@bandit.labs.overthewire.org's password: 
cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8

19-20

A bit weird...

bandit19@bandit:~$ ./bandit20-do 
Run a command as another user.
  Example: ./bandit20-do id
bandit19@bandit:~$ ./bandit20-do abc
env: ‘abc’: Permission denied

It seems to have something to do with env. When you env you can see a variable USER=bandit19. I got the idea to change that to USER=bandit20. Worked:

bandit19@bandit:~$ ./bandit20-do USER=bandit20 cat /etc/bandit_pass/bandit20
0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO

20->21

Open two SSH sessions.

In the first, listen on some port. In the other, execute the suconnect and pass the port. Then, on the listening side, enter the password for this level. The suconnect side will send back the password for the next level.

First session:

bandit20@bandit:~$ nc -l localhost 1337
0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
EeoULMCra2q0dSkYj561DX7s1CpBuOBt
bandit20@bandit:~$ 

Second session:

bandit20@bandit:~$ ./suconnect 1337
Read: 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
Password matches, sending next password
bandit20@bandit:~$ 

Instead of two sessions, you probably could also put the server process into background with &, then start suconnect <port> &, then bring back the server process to foreground, then enter stuff, etc. Didn't try this though.

21->22

bandit21@bandit:~$ cd /etc/cron.d
bandit21@bandit:/etc/cron.d$ ls
cronjob_bandit22  cronjob_bandit23  cronjob_bandit24  e2scrub_all  otw-tmp-dir  sysstat
bandit21@bandit:/etc/cron.d$ file cronjob_bandit22
cronjob_bandit22: ASCII text
bandit21@bandit:/etc/cron.d$ cat cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
bandit21@bandit:/etc/cron.d$ cat /usr/bin/cronjob_bandit22.sh 
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@bandit:/etc/cron.d$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q
bandit21@bandit:/etc/cron.d$ 

22->23

bandit22@bandit:~$ cd /etc/cron.d
bandit22@bandit:/etc/cron.d$ ls
cronjob_bandit22  cronjob_bandit23  cronjob_bandit24  e2scrub_all  otw-tmp-dir  sysstat
bandit22@bandit:/etc/cron.d$ cat cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
bandit22@bandit:/etc/cron.d$ 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
bandit22@bandit:/etc/cron.d$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
bandit22@bandit:/etc/cron.d$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
0Zf11ioIjMVN551jX3CmStKLYqjk54Ga
bandit22@bandit:/etc/cron.d$

23->24

bandit23@bandit:~$ cd /etc/cron.d                                                                                                                                                                                                                                                                                             
bandit23@bandit:/etc/cron.d$ ls                                                                                                                                                                                                                                                                                               
cronjob_bandit22  cronjob_bandit23  cronjob_bandit24  e2scrub_all  otw-tmp-dir  sysstat                                                                                                                                                                                                                                       
bandit23@bandit:/etc/cron.d$ cat cronjob_bandit24
@reboot bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
bandit23@bandit:/etc/cron.d$ 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:/etc/cron.d$ cd /var/spool/bandit24/foo
bandit23@bandit:/var/spool/bandit24/foo$ vim exploit.sh
bandit23@bandit:/var/spool/bandit24/foo$ chmod +x exploit.sh
bandit23@bandit:/var/spool/bandit24/foo$ cat /tmp/somefile123
gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8
bandit23@bandit:/var/spool/bandit24/foo$ 

exploit.sh:

#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/somefile123

24->25

bandit24@bandit:~$ for guess in {0000..9999}; do echo $guess; resp=$(echo "gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 ${guess}" | nc localhost 30002 -q 0); if [[ $resp != *"Wrong"* ]]; then break; fi; done
...
9297
bandit24@bandit:~$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 9297
Correct!
The password of user bandit25 is iCi86ttT4KSNe1armKiwbQNmB3YJP3q4

^C
bandit24@bandit:~$ 

25->26

bandit25@bandit:~$ ls
bandit26.sshkey
bandit25@bandit:~$ ssh -i bandit26.sshkey bandit26@localhost -p 2220

The shell closes the connection directly. It isn't the default shell:

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
bandit25@bandit:~$ ls -lh /usr/bin/showtext
-rwxr-xr-x 1 root root 58 Sep 19 07:08 /usr/bin/showtext

more is a pager, meaning, we can stop it from exiting immediately by decreasing the screen size of the shell to be smaller than the text to display.

Now we're in more. How to escape? When you read the manpage, you'll see a command v which switches to the vi editor. Once we're in vi, we can use the :shell command to get a shell. However, we don't want the default shell for this user but instead /bin/bash. Thus, we run :set shell=/bin/bash prior to :shell.

Now we've got a shell as user bandit26!

26->27

bandit26@bandit:~$ ls
bandit27-do  text.txt
bandit26@bandit:~$ ./bandit27-do 
Run a command as another user.
  Example: ./bandit27-do id
bandit26@bandit:~$ ./bandit27-do USER=bandit27 cat /etc/bandit_pass/bandit27
upsNCc7vzaRDx6oZC6GiR6ERwe1MowGB
bandit26@bandit:~$ 

27->28

bandit27@bandit:~$ cd $(mktemp -d)
bandit27@bandit:/tmp/tmp.WU0J0AT2mh$ git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
Cloning into 'repo'...
bandit27@bandit:/tmp/tmp.WU0J0AT2mh$ ls
repo
bandit27@bandit:/tmp/tmp.WU0J0AT2mh$ cd repo
bandit27@bandit:/tmp/tmp.WU0J0AT2mh/repo$ ls
README
bandit27@bandit:/tmp/tmp.WU0J0AT2mh/repo$ cat README
The password to the next level is: Yz9IpL0sBcCeuG7m9uQFt8ZNpS4HZRcN
bandit27@bandit:/tmp/tmp.WU0J0AT2mh/repo$ 

28->29

bandit28@bandit:~$ cd $(mktemp -d)
bandit28@bandit:/tmp/tmp.Z5aSXqX6tN$ git clone ssh://bandit28-git@localhost:2220/home/bandit28-git/repo
...
bandit28@bandit:/tmp/tmp.Z5aSXqX6tN$ cd repo/
bandit28@bandit:/tmp/tmp.Z5aSXqX6tN/repo$ ls
README.md
bandit28@bandit:/tmp/tmp.Z5aSXqX6tN/repo$ cat README.md 
# Bandit Notes
Some notes for level29 of bandit.

## credentials

- username: bandit29
- password: xxxxxxxxxx

bandit28@bandit:/tmp/tmp.Z5aSXqX6tN/repo$ git log
commit 817e303aa6c2b207ea043c7bba1bb7575dc4ea73 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date:   Thu Sep 19 07:08:39 2024 +0000

    fix info leak

commit 3621de89d8eac9d3b64302bfb2dc67e9a566decd
Author: Morla Porla <morla@overthewire.org>
Date:   Thu Sep 19 07:08:39 2024 +0000

    add missing data

commit 0622b73250502618babac3d174724bb303c32182
Author: Ben Dover <noone@overthewire.org>
Date:   Thu Sep 19 07:08:39 2024 +0000

    initial commit of README.md
bandit28@bandit:/tmp/tmp.Z5aSXqX6tN/repo$ git show 817e303aa6c2b207ea043c7bba1bb7575dc4ea73
commit 817e303aa6c2b207ea043c7bba1bb7575dc4ea73 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date:   Thu Sep 19 07:08:39 2024 +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: 4pT1t5DENaYuqnqvadYs1oE4QLCdjmJ7
+- password: xxxxxxxxxx

bandit28@bandit:/tmp/tmp.Z5aSXqX6tN/repo$ 

29->30

bandit29@bandit:~$ cd $(mktemp -d)
bandit29@bandit:/tmp/tmp.gKZYFRxq5T$ git clone ssh://bandit29-git@localhost:2220/home/bandit29-git/repo
bandit29@bandit:/tmp/tmp.gKZYFRxq5T/repo$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/origin/sploits-dev
bandit29@bandit:/tmp/tmp.gKZYFRxq5T/repo$ git switch dev
branch 'dev' set up to track 'origin/dev'.
Switched to a new branch 'dev'
bandit29@bandit:/tmp/tmp.gKZYFRxq5T/repo$ ls
bandit29@bandit:/tmp/tmp.gKZYFRxq5T/repo$ cat README.md 
# Bandit Notes
Some notes for bandit30 of bandit.

## credentials

- username: bandit30
- password: qp30ex3VLz5MDG1n91YowTv4Q8l7CDZL

bandit29@bandit:/tmp/tmp.gKZYFRxq5T/repo$

30->31

bandit30@bandit:~$ cd $(mktemp -d)
bandit30@bandit:/tmp/tmp.M2jmeJ11sI$ git clone ssh://bandit30-git@localhost:2220/home/bandit30-git/repo
bandit30@bandit:/tmp/tmp.M2jmeJ11sI/repo$ git tag
secret
bandit30@bandit:/tmp/tmp.M2jmeJ11sI/repo$ git show secret
fb5S2xb7bRyFmAvQYQGEqsbhVyJqhnDy

31->32

bandit31@bandit:~$ cd $(mktemp -d)
bandit31@bandit:/tmp/tmp.gX2YOn7wIs$ git clone ssh://bandit31-git@localhost:2220/home/bandit31-git/repo
bandit31@bandit:/tmp/tmp.gX2YOn7wIs$ cd repo/
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/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
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ echo "May I come in?" > key.txt
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

That's strange... Ahh, probably there's a .gitignore

bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ cat .gitignore 
*.txt
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ rm .gitignore
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ ls
key.txt  README.md
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    .gitignore

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        key.txt

no changes added to commit (use "git add" and/or "git commit -a")
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ echo "May I come in?" > key.txt
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git add .
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    .gitignore
        new file:   key.txt

bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git commit -m "give me my flag!"
[master e85ed8b] give me my flag!
 2 files changed, 1 insertion(+), 1 deletion(-)
 delete mode 100644 .gitignore
 create mode 100644 key.txt
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$ git push
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/bandit31/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit31/.ssh/known_hosts).
                         _                     _ _ _   
                        | |__   __ _ _ __   __| (_) |_ 
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_ 
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


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

bandit31-git@localhost's password: 
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes | 292.00 KiB/s, done.
Total 3 (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: 3O9RfhqyAlVBEZpVb6LYStshZoqoSx5K 
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'
bandit31@bandit:/tmp/tmp.gX2YOn7wIs/repo$

32->33

WELCOME TO THE UPPERCASE SHELL                                                 
>> asdf                                                                        
sh: 1: ASDF: Permission denied

All input is transformed to uppercase letters before being evaluated. This sucks because Linux commands, and the filesystem paths are case sensitive.

That means we can only use stuff that is uppercase already (e.g. variables listed by env), or non-letters (i.e. numbers, special chars).

What's really handy is that Linux stores the first argument of a command (e.g. ./foo when invoking ./foo 1 2 3) in the variable 0. In case of our interactive shell, it stores the path to the shell in 0.

This means that we can simply use $0 to spawn a new "normal" shell.

>> $0
$ whoami
bandit33
$ which $SHELL
/home/bandit32/uppershell
$ ls
uppershell
$ cat /etc/bandit_pass/bandit33
tQdtbs5D5i2vJwkO8mEyYEyTL8izoeJ0
$ exit

33

bandit33@bandit:~$ ls
README.txt
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!
bandit33@bandit:~$ exit
logout
Connection to bandit.labs.overthewire.org closed.

What I've Learned

What this CTF has thaught me (again):

  • some find options: find / -size 33c -user bandit7 -group bandit6
  • how to undo a hexdump: xxd -r data.txt
  • how to decompress files: cat compressed_file | {gzip,bzip2} -d > decompressed_file
  • how to connect to a TLS port: openssl s_client <host>:<port>
  • that looking into /etc/cron.d/ might be useful to escalate privileges
  • that $0 contains a reference to the current shell

SSH -- Too many authentication failures

I have quite a few SSH keypairs in ~/.ssh/. By default, the client tries all of these keys when connecting to the gameserver. You can see that by adding the ssh -v ... option:

...
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
... <trying all the keys> ...

Since none of them matches (password-based authentication), and the /etc/ssh/sshd_config on the server likely contains something like MaxAuthTries 3, it'll send me

Received disconnect from <IP> port 2220:2: Too many authentication failures

at some point.

To prevent this, tell the client to prefer password-based authentication via the ssh -o PreferredAuthentications=password flag. You can see that it first tries the password-based authentication now:

...
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: password
...

Unrelated Thoughts

Some unrelated (privacy) concerns: I realized that I can see the IPs of all users that connected or still are connected via last (consults /var/log/wtmp) and who (consults /var/run/utmp), or netstat -tn, etc. I wonder if you could reconstruct which organizations use that CTF for training...

I can also see the pseudo-terminal their assigned (i.e. /dev/pts/X). I wonder if a non-root player could spy on other players through monitoring such a device file. Not sure; didn't try. Maybe I'll try it sometime on my own server.


Previous

(Patching a Binary)