baby steps to netsec
Wargame BANDIT
SSH : bandit.labs.overthewire.org:2220
Level 1 to 20
The wargames offered by the OverTheWire community can help you to learn and practice security concepts in the form of fun-filled games. I highly recommend it for every one to have a look at their awesome website. Here is my effort on the first and simplest Wargame listed : Bandit. I have summarised a list of concepts learned in each Level of the game.
Bandit0 | Bandit0
file readme has password for Bandit1 : boJ9jbbUNNfktd78OOpsqOltutMc3MY1
Commands learned
use \>man [COMMAND] to get help on the command and if that fails use \>help [COMMAND]
| COMMAND | Description | Usage Example |
|---|---|---|
ls |
list directory contents | ls |
cd |
Change the shell working directory | cd |
cat |
concatenate files and print on the standard output | cat [FILENAME] |
file |
determine file type | file [FILENAME] |
du |
estimate file space disk usage | du |
find |
search for files in a directory hierarchy | find [FILENAME] |
BANDIT1 | boJ9jbbUNNfktd78OOpsqOltutMc3MY1
Accessing files named with just a hyphen
task is to read a file convinientsly named with just a hyphen -
The problem now is that most commands accept arguments prefixed with a hyphen and cat
will have issues parsing just a stand alone hyphen.
I tried using a common trick of enclosing the hyphen in quotes but "-" did
not seem to do the trick either.
So now I used an expression i have often seen in many scripts,
where a executable in the current directory is referred to as ./filename
so I use cat ./- to successfully get password to the next level : CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9
BANDIT2 | CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9
Accessing files with spaces in its name
Remember how in the previous level i tried enclosing the filename with quotes, yup that worked in this level.
Ran cat "file name with spaces" to get password for next level UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK
BANDIT3 | UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK
Accessing hidden files
there is a .hidden file not visible on a simple ls so go for the pro version and use : ls -a
or even better ls -l -a to see it has access specified as : -rw-r-----
A hidden file is anything beginning with a . but I used this excersize to explore file permissions.

cat .hidden gives pIwrPrtPN36QITSp3EQaw936yaFoFgAB
ta-da !
BANDIT4 | pIwrPrtPN36QITSp3EQaw936yaFoFgAB
Has a folder called readme with 10 file from -file00 to -file09
yup, the names start with a hyphen, how convinient. Use cat ./-* to see all at once.
-file07 has qwhat looks like a password. Rest of them contain non-ascii stuff, not sure if they can be used as passwords.
MSDN recommends sing Unicode Characters in ALT Key Combinations
BANDIT5 | koReBOKuIDDepwhWk7jZC0RTdopnAYKh
Has a list of 20 folders maybehere00 to maybehere19 with files in it with spaces in its name as well as with hyphen and dot prefix.
Of course you can search one by one, its only 20 folders, but that is not the reason you started this, did you ?
So how do we iterrate over the folders in root directory and see content of all its files (with unconventional yet valid names).
The problem lists three unique features about the file :
- human-readable
- 1033 bytes in size
- not executable
Almost all are human readable you will notice so thats not really helpful. Size is 1033 bytes exact, thats a very strong hint.
Use command du -a to see size of all files in all folders. But size isn't in bytes, for that use additional -b argument.
Voila ! .file2 in maybehere07 is seen of size 1033 in plain sight ! A lot of empty space is trailing the actual password so that
had the size not be mentioned you could have isolated this one file just by its abnosrmal small size (rest are quite bigger!).
But this was a very poor solution, there is obviously a more sophisticated way of solving this that helps you not
manually parse a long list for the number 1033. find is the command to use here.
find -size 1033c quickly returns ./maybehere07/.file2 which hass password DXjZPULLxYr17uwoI01bNLQbtFemEgo7
BANDIT6 | DXjZPULLxYr17uwoI01bNLQbtFemEgo7
Okay this got me stumped for sometime. The folder where you spawn has nothing worthwhile in it. The total size of the folder is less than the password file size (33bytes)
so naturally, I drift to the root. and the command for previous level does equally well, I do add an additional -user and -group arguments.
On execution of find -size 33c -user bandit7 -group bandit6 most opf the files are denied permission but this one caught my eye :
./var/lib/dpkg/info/bandit7.password, yup and the password works for bandit7 !
BANDIT7 | HKBPTKQnIay4Fw76bEy8PVxKEDQRKTzs
Ah ! the famous grep. This level needs you to parse data.txt file for the work "millionth" for the password to the next level.
The solution is too simple so explore this level experimenting and learning about grep. Its quite powerful.
BANDIT8 | cvX2JJa4CFALtqS87jk27qwqGhBM9plV
At this point I noticed that the level description wishes you to familiarize your self with the following commands :
| COMMAND | Description | Usage Example |
|---|---|---|
grep |
grep, egrep, fgrep, rgrep - print lines matching a pattern | grep [OPTIONS] PATTERN [FILE...] |
sort |
sort lines of text files | sort [OPTION]... [FILE]... |
uniq |
report or omit repeated lines | uniq [OPTION]... [INPUT [OUTPUT]] |
strings |
print the strings of printable characters in files. | strings filename |
base64 |
base64 encode/decode data and print to standard output | base64 [OPTION]... [FILE] |
tr |
translate or delete characters | tr [OPTION]... SET1 [SET2] |
tar |
The GNU version of the tar archiving utility | tar --extract --get [options] [pathname ...] |
gzip |
gzip, gunzip, zcat - compress or expand files | gzip [ -acdfhklLnNrtvV19 ] [--rsyncable] [-S suffix] [ name ... ] |
bzip2 |
a block-sorting file compressor, v1.0.6 | ... |
bzcat |
decompresses files to stdout | ... |
bzip2recover |
recovers data from damaged bzip2 files | ... |
xxd |
make a hexdump or do the reverse | xxd [options] [infile [outfile]] |
uniq lookes like a tempting option, but neither -c nor -u readily spew out any answer.
sort is promising but by itself alone it will leave you with manual task of seeing the password stick out out of all clubbed strings.
Why not both ? Welcome pipes | ... using sort data.txt | uniq -u does the trick (sort data.txt | uniq -u)
BANDIT9 | UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR
Much like the previous level we are to find readable "strings" where the password is prefixed with many '=' signs.
Pipes to the resque again. strings will print all readable strings and grep will find the unspecified amount of = signs for us.
strings data.txt | grep === does the job and neatly prints four strings where the first three are "the", "password","is", how convinient.
BANDIT10 | truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
Regarding the base64 command, this one is fairly introductory. Use base64 -d data.txt
Readup on base64 at wikipedia ?
BANDIT11 | IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR
This regards the ROT13 encoding. From the translate command trexample on wikipedia
you know what to do : cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
BANDIT12 | 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu
Okay, this one will make you work some, at least I did. I am not proud of my solution as it involved manual task and
the file is encrypted / tarred only a few times.
This involves introductory knowledge of xxd, tar, gzip and bzip.
The data.txt you come across is the hex dump of the original compressed binary.
use the file command to know what operation to do on resulting file.
If its gzip compressed data use gzip -d filename to decompress.
If its POSIX tar archive (GNU) use tar -xvf tarballname
Occasionaly the command fails due to unrecognizable extension. so using mv command rename resulting file to bz,gz or tar
Around 8 to 9 levels deep you get an ASCII text file with the password.
I will revisit this one to find an iterative solution, life is too small to iterate manually. If you still see the above line promising iterative solution, I am a lazy bum and havent come back to this problem. Sorry.
BANDIT13 | 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL
You must familiarize yourself to these new set of commands for the next few levels :
ssh, telnet, nc, openssl, s_client, nmap
| COMMAND | Description |
|---|---|
ssh |
OpenSSH SSH client (remote login program) |
telnet |
user interface to the TELNET protocol |
nc |
arbitrary TCP and UDP connections and listens |
openssl |
OpenSSL Commandline tool |
s_client |
SSL/TLS client program |
nmap |
Network exploration tool and security / port scanner |
In this level you just have to use the given PEN RSA Private Key file to login to the next level Bandit14.
From above description table ssh looks like a good candidate command to use here. Since bandit14 is local to same
system we can refer to the target as bandit14@localhost.
The following command logs you in automatically to the next level :
ssh -i sshkey.private bandit14@localhost
BANDIT14 | SSH login using key sshkey.private | 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
The password for the next level has to be retrieved by submitting the password of the current level to port 30000 on localhost.
Since we logged in using the private key, once we login we can see the actual password by cat /etc/bandit_pass/bandit14.
now nc can be used to connect to localhost:30000 . Pipe the previous cat command with nc localhost 30000 to see password to
the next level.
BANDIT15 | BfMYroe26WYalil77FoDi9qh59eK5xNr
Now you must submit the password of the current level to port 30001 on localhost using SSL encryption.
Again, the current password is here /etc/bandit_pass/bandit15. We pipe this with openssl command.
The problem also hints with the following information : Getting “HEARTBEATING” and “Read R BLOCK”? Use -ign_eof and read the “CONNECTED COMMANDS” section in the manpage. Next to ‘R’ and ‘Q’, the ‘B’ command also works in this version of that command…
CONNECTED COMMANDS tells us the following If a connection is established with an SSL server then any data received from the server is displayed and any key presses will be sent to the server. When used interactively (which means neither -quiet nor -ign_eof have been given), the session will be renegotiated if the line begins with an R, and if the line begins with a Q or if end of file is reached, the connection will be closed down.
Interesting, its worth exploring here, but finally you will conclude that the following is enough :
cat /etc/bandit_pass/bandit15 | openssl s_client -connect localhost:30001 -ign_eof
BANDIT16 | cluFn7wTiGryunymYOu4RcffSxQluehd
The Problem : The credentials for the next level can be retrieved by submitting the password of the current level to a port on localhost in the range 31000 to 32000. First find out which of these ports have a server listening on them. Then find out which of those speak SSL and which don’t. There is only 1 server that will give the next credentials, the others will simply send back to you whatever you send to it.
The wargame has reached an interesting curve and we are to get ourselves familiar with port scanning.
using the famous nmap command we wet our hands into port sniffing. Smells like hacking already, eh ? I recommend you glance over the port scanning basics here
nmap -sV -p 31000-32000 localhost gets us a list of 5 ports in the required range with three that list echo as the service. We ignore these and pay attention to the other two ports which list msdtc Microsoft Distributed Transaction Coordinator (error) as the running service.
echo cluFn7wTiGryunymYOu4RcffSxQluehd | openssl s_client -quiet -connect localhost:31790
Now using the openssl s_client command on connecting to 31518 and pushing the current password, we are given a ssh private ke to login to the next level. lets save this in tmp/key/sshkey.private
Now use this key to login to level 17. Sounds familiar ? Because its same as Level 13 !
The following command ushers you into the realm of Level 17 : ssh -i sshkey.private bandit17@localhost
Note : Probably this command will ignore the key with error WARNING: UNPROTECTED PRIVATE KEY FILE!
The file must be only readable by you ! chmod 400 sshkey.private should take care of that.
BANDIT17 | xLYVMN9WE5zQ5vHacb0sZEVqbrp7nBTn
The Problem : There are 2 files in the homedirectory: passwords.old and passwords.new. The password for the next level is in passwords.new and is the only line that has been changed between passwords.old and passwords.new
diff is listed under Commands you may need to solve this level and seems obvious to use here.
diff passwords.old passwords.newresults in
`42c42
< eG69HnVwO1p7cOdfhadHkPv8Vn0ChedC
kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd`
so logging in into bandit18 using kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd gets you in but immediate thrown out with a byebye!
Thats expected and related to the next level.
Note : to know the actual password of current level see /etc/bandit_pass/bandit17
BANDIT18 | kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd
The Problem : The password for the next level is stored in a file readme in the homedirectory. Unfortunately, someone has modified .bashrc to log you out when you log in with SSH.
Password is present as plaintext in readme, thats convinient. The problem is the problematic bashrc. If there was only a way from ssh to not trigger the bashrc script. A study of ssh gets us to -t : Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty. Use this opportunity to learn about bash.
ssh -t bandit18@localhost /bin/sh gets you in safely, minus the command prompt prefix.
BANDIT19 | IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x
The Problem : To gain access to the next level, you should use the setuid binary in the homedirectory. Execute it without arguments to find out how to use it. The password for this level can be found in the usual place (/etc/bandit_pass), after you have used the setuid binary.
setuid : short for "set user ID upon execution", read more about it here.
on executing the file ./bandit20-do in home folder you get :
Run a command as another user. Example: ./bandit20-do id
So thats exactly what we do, piggyback on this file to read password as another user (bandit20)
./bandit20-do cat /etc/bandit_pass/bandit20 gets us GbKksEFF4yrVs6il55v6gwY5aVje5f0j
BANDIT20 | GbKksEFF4yrVs6il55v6gwY5aVje5f0j
The Problem : There is a setuid binary in the homedirectory that does the following: it makes a connection to localhost on the port you specify as a commandline argument. It then reads a line of text from the connection and compares it to the password in the previous level (bandit20). If the password is correct, it will transmit the password for the next level (bandit21).
NOTE: Changes to the infrastructure made this level more difficult. You will need to figure out a way to launch multiple commands in the same Docker instance.
NOTE 2: Try connecting to your own network daemon to see if it works as you think
We are now well aware og setuid binaries, in this the binary queries a port for current level's password and spits out next level's password if the password provided was correct. We first neet to setup a service at a port that repeats the levels password, for this we use nc -l 12345 < /etc/bandit_pass/bandit20. But wait, how do we free up the prompt for another ssh session to run the setuid binary ? For that we postfix the commandline by &. The command prompt appears immediately to accept the next command ./suconnect 12345 which spews out the next level's password gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr
I would recommend you go back at this point and revise all concepts you have learned so far in levels 1 to 20. Though a game, the point is to actually retain all the information once the game is over. Practice. Practice. Practice.
See you in next post where we wrap up the BANDIT series of OverTheWire wargames !