OverTheWire to projekt społecznościowy hostowany na GitHub. Stanowi on kolekcję gier typu hackme, dzięki którym możemy sprawdzić i poszerzyć swoją wiedzę z dziedziny o *nixach i zabezpieczeniach. Wyróżniającą cechą OverTheWire jest forma zadań, które rozwiązujemy na rzeczywistych systemach.

W dzisiejszym wpisie opiszę rozwiązania wszystkich etapów gry Bandit. Celem wpisu jest pomoc osobom, które utknęły w trakcie rozwiązywania zadań.

Rozwiązania

Do rozwiązania zadań potrzebny będzie klient SSH. Jeśli pracujesz w systemach Linux/Unix do połączenia posłuży Ci komenda ssh w terminalu. W systemach Windows posłużyć może putty, którego krótki opis znajdziemy pod tym adresem. Do rozwiązania zadań posłużyłem się komputerem z systemem Linux.

Rozwiązanie każdego poziomu polegać będzie na uzyskaniu dostępu do konta banditN gdzie N będzie liczbą od 1 do 25 kolejno dla zadań. Każdorazowo będziemy łączyć się z hostem bandit.labs.overthewire.org.

Bandit Level 0 → Level 1

Rozwiązanie pierwszego zadania polega na odczytaniu pliku readme

michal@netbook:~$ ssh bandit0@bandit.labs.overthewire.org
bandit0@melinda:~$ cat readme
boJ9jbbUNNfktd78OOpsqOltutMc3MY1

Bandit Level 1 → Level 2

Z użyciem uzyskanego hasła logujemy się jako bandit1. Problem z odczytaniem pliku - polega na tym, ze jest to znak specjalny i nie zostanie zinterpretowany jako prawidłowa nazwa pliku. Odwołujemy się zatem z użyciem referencji do katalogu lokalnego.

michal@netbook:~$ ssh bandit1@bandit.labs.overthewire.org
bandit1@melinda:~$ cat ./-
CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9

Bandit Level 2 → Level 3

Nazwa kolejnego pliku zawiera spacje. Odczyt pliku ze spacjami polega wyróżnieniu każdej z nich wstawiając znak \

michal@netbook:~$ ssh bandit2@bandit.labs.overthewire.org
bandit2@melinda:~$ ls
spaces in this filename
bandit2@melinda:~$ cat spaces\ in\ this\ filename 
UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK

Bandit Level 3 → Level 4

Nazwy plików ukrytych w systemie Linux poprzedza kropka

michal@netbook:~$ ssh bandit3@bandit.labs.overthewire.org
bandit3@melinda:~$ cd inhere/
bandit3@melinda:~/inhere$ ls -all
total 12
drwxr-xr-x 2 root    root    4096 Nov 14 10:32 .
drwxr-xr-x 3 root    root    4096 Nov 14 10:32 ..
-rw-r----- 1 bandit4 bandit3   33 Nov 14 10:32 .hidden
bandit3@melinda:~/inhere$ cat .hidden
pIwrPrtPN36QITSp3EQaw936yaFoFgAB

Bandit Level 4 → Level 5

Katalog inhere zawiera pliki, pośród których jeden jest czytelny. Do określenia typu plików posłuży nam polecenie find

michal@netbook:~$ ssh bandit4@bandit.labs.overthewire.org
bandit4@melinda:~/inhere$ file ./*
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text
./-file08: data
./-file09: data
bandit4@melinda:~/inhere$ cat ./-file07
koReBOKuIDDepwhWk7jZC0RTdopnAYKh

Bandit Level 5 → Level 6

Do rozwiązania tego etapu wystarczy zapoznać się z man find

michal@netbook:~$ ssh bandit5@bandit.labs.overthewire.org
bandit5@melinda:~$ find inhere/ -size 1033c -type f
inhere/maybehere07/.file2
bandit5@melinda:~$ cat inhere/maybehere07/.file2
DXjZPULLxYr17uwoI01bNLQbtFemEgo7	

Bandit Level 6 → Level 7

Po raz kolejny zastosujemy find. Argument 2>/dev/null powoduje, że find będzie drukował błędy do /dev/null, czyli nie będą wyświetlane na ekranie.

michal@netbook:~$ ssh bandit6@bandit.labs.overthewire.org
bandit6@melinda:/$ find / -group bandit6 -user bandit7 -size 33c 2>/dev/null
/var/lib/dpkg/info/bandit7.password
bandit6@melinda:/$ cat /var/lib/dpkg/info/bandit7.password 
HKBPTKQnIay4Fw76bEy8PVxKEDQRKTzs

Bandit Level 7 → Level 8

michal@netbook:~$ ssh bandit7@bandit.labs.overthewire.org
bandit7@melinda:~$ cat data.txt | grep millionth
millionth	cvX2JJa4CFALtqS87jk27qwqGhBM9plV

Bandit Level 8 → Level 9

Do rozwiązania posłuży nam uniq. Zastosowanie uniq -u na posortowanych danych zwróci nam unikalne linie pliku.

michal@netbook:~$ ssh bandit8@bandit.labs.overthewire.org
bandit8@melinda:~$ sort data.txt | uniq -u
UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR

Bandit Level 9 → Level 10

Za pomocą polecenia string wyszukamy czytelne ciągi łańcuchowe, których listę odfiltrujemy pod kątem tych, które rozpoczynają się od znaków równości

michal@netbook:~$ ssh bandit9@bandit.labs.overthewire.org
bandit9@melinda:~$ strings data.txt | grep ==
I========== the6
========== password
========== ism
========== truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk

Bandit Level 10 → Level 11

Wystarczy zdekodować zawartość pliku data.txt

michal@netbook:~$ ssh bandit10@bandit.labs.overthewire.org	
bandit10@melinda:~$ base64 -d data.txt 
The password is IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR

Bandit Level 11 → Level 12

Do odwrócenia zakodowania zastosujemy tr.

michal@netbook:~$ ssh bandit11@bandit.labs.overthewire.org
bandit11@melinda:~$ cat data.txt | tr '[A-Za-z]' '[N-ZA-	Mn-za-m]'
The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu

Bandit Level 12 → Level 13

W rozwiązaniu tego zadania pomogą nam polecenia xxd oraz file. Najpierw zdekodujemy plik, następnie będziemy rozpoznawać typ kompresji i rozpakowywać plik.

michal@netbook:~$ ssh bandit12@bandit.labs.overthewire.org
bandit11@melinda:~$ mkdir /tmp/michalp11/
bandit11@melinda:~$ cd /tmp/michalp11/
bandit11@melinda:/tmp/michalp11$ xxd -r ~/data.txt dane
bandit12@melinda:/tmp/michalp11$ file dane  
dane: gzip compressed data, was "data2.bin", from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/michalp11$ file dane
dane: bzip2 compressed data, block size = 900k
bandit12@melinda:/tmp/michalp11$ bunzip2 dane
bunzip2: Can't guess original name for dane -- using dane.out
bandit12@melinda:/tmp/michalp11$ file dane.out 
dane.out: gzip compressed data, was "data4.bin", from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/michalp11$ mv dane.out dane.gz
bandit12@melinda:/tmp/michalp11$ gunzip dane.gz
bandit12@melinda:/tmp/michalp11$ file dane
dane: POSIX tar archive (GNU)
bandit12@melinda:/tmp/michalp11$ tar xvf dane
data5.bin
bandit12@melinda:/tmp/michalp11$ file data5.bin  
data5.bin: POSIX tar archive (GNU)
bandit12@melinda:/tmp/michalp11$ tar xvf data5.bin 
data6.bin
bandit12@melinda:/tmp/michalp11$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
bandit12@melinda:/tmp/michalp11$ mv data6.bin data6.bz
bandit12@melinda:/tmp/michalp11$ bunzip2 data6.bz
bandit12@melinda:/tmp/michalp11$ file data6
data6: POSIX tar archive (GNU)
bandit12@melinda:/tmp/michalp11$ tar xvf data6
data8.bin
bandit12@melinda:/tmp/michalp11$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/michalp11$ mv data8.bin data8.gz
bandit12@melinda:/tmp/michalp11$ gunzip data8.gz
bandit12@melinda:/tmp/michalp11$ file data8
data8: ASCII text
bandit12@melinda:/tmp/michalp11$ cat data8
The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL

Bandit Level 13 → Level 14

W tym zadaniu kluczowe jest wykorzystanie ssh. Należy wykorzystać za pomocą parametru -i dostarczony nam klucz prywatny

michal@netbook:~$ ssh bandit13@bandit.labs.overthewire.org	
bandit13@melinda:~$ ssh bandit14@localhost -i sshkey.private 
...
bandit14@melinda:~$ cat /etc/bandit_pass/bandit14
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e

Bandit Level 14 → Level 15

Do wysłania danych nieszyfrowanych na serwer pod wskazany port wykorzystamy telnet

bandit14@melinda:~$ cat /etc/bandit_pass/bandit14
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
bandit14@melinda:~$ telnet localhost 30000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
Correct!
BfMYroe26WYalil77FoDi9qh59eK5xNr

Bandit Level 15 → Level 16

Analogicznie do poprzedniego zadania, jednak w sposób szyfrowany wyślemy dane na port 30001

bandit14@melinda:~$ openssl s_client -host localhost -port 30001 -quiet
depth=0 CN = li190-250.members.linode.com
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = li190-250.members.linode.com
verify return:1
BfMYroe26WYalil77FoDi9qh59eK5xNr
Correct!
cluFn7wTiGryunymYOu4RcffSxQluehd

Bandit Level 16 → Level 17

Pierwszy krok to skanowanie portów, w tym celu użyjemy nmap

bandit14@melinda:~$ nmap -v -A -p 31000-32000 localhost

Starting Nmap 6.40 ( http://nmap.org ) at 2015-02-09 19:51 UTC
...
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0010s latency).
Not shown: 996 closed ports
PORT      STATE SERVICE VERSION
31046/tcp open  echo
31518/tcp open  msdtc   Microsoft Distributed Transaction Coordinator (error)
31691/tcp open  echo
31790/tcp open  msdtc   Microsoft Distributed Transaction Coordinator (error)
31960/tcp open  echo
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Serwery echa eliminujemy od razu, sprawdzamy tylko 31518 i 31790. Test portu 31518:

bandit14@melinda:~$ openssl s_client -host localhost -port 31518 -quiet
depth=0 CN = li190-250.members.linode.com
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = li190-250.members.linode.com
verify return:1
test
test

Na test odpowiedział tym samym, więc port 31790 będzie prawidłowy.

bandit14@melinda:~$ openssl s_client -host localhost -port 31790 -quiet
depth=0 CN = li190-250.members.linode.com
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = li190-250.members.linode.com
verify return:1
cluFn7wTiGryunymYOu4RcffSxQluehd
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-----

read:errno=0

Klucz RSA zapisałem na lokalnym komputerze jako bandit17.rsa. Należy nadać mu ograniczone uprawnienia chmod 600.

Bandit Level 17 → Level 18

Wystarczy zastosować diff

bandit17@melinda:~$ diff passwords.old passwords.new
42c42
< BS8bqB1kqkinKJjuxL6k072Qq9NRwQpR
---
> kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd

Bandit Level 18 → Level 19

Nie wylogowując się z bandit17 wywołamy zdalną metodę

bandit17@melinda:~$ ssh bandit18@localhost cat readme
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is 05:3a:1c:25:35:0a:ed:2f:cd:87:1c:f6:fe:69:e4:f6.
Are you sure you want to continue connecting (yes/no)? yes
...
bandit18@localhost's password: 
IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x

Bandit Level 19 → Level 20

Wywołujemy metodę na uprawnieniach innego użytkownika

bandit19@melinda:~$ ./bandit20-do 
Run a command as another user.
  Example: ./bandit20-do id
bandit19@melinda:~$ ./bandit20-do cat /etc/bandit_pass/bandit20
GbKksEFF4yrVs6il55v6gwY5aVje5f0j

Bandit Level 20 → Level 21

Idea rozwiązania: stworzyć serwer, który wyśle tekst “GbKksEFF4yrVs6il55v6gwY5aVje5f0j” do klienta a następnie odbierze nowe hasło. Klientem będzie wskazany w zadaniu program suconnect. Uruchmiamy serwer za pomocą netcat:

bandit20@melinda:~$ nc -l 9999
GbKksEFF4yrVs6il55v6gwY5aVje5f0j

Uruchamiamy klienta (uprzednio w innym oknie łączymy się ponownie na konto bandit20, nie zamykając poprzedniego połączenia)

bandit20@melinda:~$ ./suconnect 9999
Read: GbKksEFF4yrVs6il55v6gwY5aVje5f0j
Password matches, sending next password

Na terminalu serwera wynik zmieni się na:

bandit20@melinda:~$ nc -l 9999
GbKksEFF4yrVs6il55v6gwY5aVje5f0j
gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr

Bandit Level 21 → Level 22

Badamy zadanie cron

bandit21@melinda:~$ ls /etc/cron.d
behemoth4_cleanup   manpage3_resetpw_job   natas27_cleanup  sysstat
cron-apt            melinda-stats          php5             vortex0
cronjob_bandit22    natas-session-toucher  semtex0-32       vortex20
cronjob_bandit23    natas-stats            semtex0-64
cronjob_bandit24    natas25_cleanup        semtex0-ppc
leviathan5_cleanup  natas26_cleanup        semtex5
bandit21@melinda:~$ cat /etc/cron.d/cronjob_bandit22
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
bandit21@melinda:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@melinda:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI

Bandit Level 22 → Level 23

Zmodyfikujemy skrypt wykonywany przez CRON aby dowiedzieć się, gdzie szukać hasła

bandit22@melinda:~$ ls /etc/cron.d/
behemoth4_cleanup   manpage3_resetpw_job   natas27_cleanup  sysstat
cron-apt            melinda-stats          php5             vortex0
cronjob_bandit22    natas-session-toucher  semtex0-32       vortex20
cronjob_bandit23    natas-stats            semtex0-64
cronjob_bandit24    natas25_cleanup        semtex0-ppc
leviathan5_cleanup  natas26_cleanup        semtex5
bandit22@melinda:~$ cat /etc/cron.d/cronjob_bandit23
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
bandit22@melinda:~$ 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@melinda:~$ mkdir /tmp/michalp23
bandit22@melinda:~$ cp /usr/bin/cronjob_bandit23.sh /tmp/michalp23

W ulubionym edytorze otwórz plik /tmp/michalp23/cronjob_bandit23.sh i zmodyfikuj następująco:

#!/bin/bash

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

echo "/tmp/$mytarget"

Teraz wywołamy nasz skrypt i dowiemy się gdzie znajduje się hasło.

bandit22@melinda:~$ /tmp/michalp23/cronjob_bandit23.sh 
/tmp/8ca319486bfbbc3663ea0fbe81326349
bandit22@melinda:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n

Bandit Level 23 → Level 24

Przez analogię analizujemy kolejny skrypt cron

bandit23@melinda:~$ cat /etc/cron.d/cronjob_bandit24
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
bandit23@melinda:~$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash

myname=$(whoami)

cd /var/spool/$myname
echo "Executing and deleting all scripts in /var/spool/$myname:"
for i in *;
do
    echo "Handling $i"
    ./$i
    rm -f $i
done

bandit23@melinda:~$ mkdir /tmp/michalp24
bandit23@melinda:~$ cd /tmp/michalp24
bandit23@melinda:/tmp/michalp24$ touch wynik 
bandit23@melinda:/tmp/michalp24$ touch skrypt.sh
bandit23@melinda:/tmp/michalp24$ chmod 777 ./*

Edytujemy skrypt.sh ulubionym edytorem wstawiając zawartość:

#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/michalp24/wynik

Następnie w konsoli:

bandit23@melinda:/tmp/michalp24$ cp skrypt.sh /var/spool/bandit24/
bandit23@melinda:/tmp/michalp24$ cron
bandit23@melinda:/tmp/michalp24$ cat wynik
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ

Bandit Level 24 → Level 25

Istnieje wiele możliwych rozwiązań tego zadania. Moja propozycja to skrypt w Python na podstawie przykładowego kodu klienta telnet

# telnet program example
import socket, select, string, sys
 
if __name__ == "__main__":
     
    if(len(sys.argv) < 3) :
        print 'Usage : python telnet.py hostname port'
        sys.exit()
     
    host = sys.argv[1]
    port = int(sys.argv[2])
     
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)
    # spróbuj połączenia
    try :
        s.connect((host, port))
    except :
        print 'Unable to connect'
        sys.exit()
     
    print 'Connected to remote host'
    i=0     
    while 1:
        socket_list = [sys.stdin, s]
        passwd = "UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ %04d\n" %(i,)
    i += 1 
        # Pobranie listy czytelnych gniazd
        read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
         
        for sock in read_sockets:
            #Otrzymano odpowiedź z serwera
            if sock == s:
                data = sock.recv(4096)
                if not data :
                    print 'Connection closed'
                    sys.exit()
                else :
                    sys.stdout.write(data)             

            else :
        print passwd
        s.send(passwd)

Plik umieszczamy jak poprzednio w katalogu roboczym, wedle uznania utworzonym w /tmp, nadajemy chmod 755 i uruchamiamy ./nazwapliku localhost 30002

Skrypt jest dość prymitywny, jego wykonanie spowoduje odpytanie serwera wszystkimi możliwymi kombinacjami. Jedną z odpowiedzi serwera będzie Correct! oraz hasło uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG.

Bandit Level 25 → Level 26

Ostatni poziom roziwązujemy dzięki znajomości more i obsłudze vim. Logowanie przebiega podobnie jak dla bandit14 czy bandit17, za pomocą klucza danego nam w katalogu domowym. Pierwszy krok to określenie powłoki użytkownika bandit26.

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

more ~/text.txt
exit 0

Logowanie na konto bandit26 powoduje jak widać w skrypcie jedynie odczytanie zawartości /home/bandit26/text.txt, którego nie możemy modyfikować. Logowanie przebiega następująco:

  _                     _ _ _   ___   __  
 | |                   | (_) | |__ \ / /  
 | |__   __ _ _ __   __| |_| |_   ) / /_  
 | '_ \ / _` | '_ \ / _` | | __| / / '_ \ 
 | |_) | (_| | | | | (_| | | |_ / /| (_) |
 |_.__/ \__,_|_| |_|\__,_|_|\__|____\___/ 
Connection to localhost closed.
bandit25@melinda:~$ 

Znajomość zachowania more pozwala zauważyć, że jeśli okno terminala jest za małe program nie zakończy działania lecz pozwoli przewijać tekst. Zmniejszmy zatem rozmiar okna do minimalnej możliwej wysokości i ponownie przeprowadźmy logowanie. Program uruchomił się w trybie przewijania. Możemy teraz nacisnąć v i uzyskać dostęp do linii komend podobnej do tej w vi. Należy wpisać polecenie :r /etc/bandit_pass/bandit26 , następnie możemy powiększyć okno. Program more otworzy oplik zawierający ostatnie hasło w grze.