Sunday 4 May 2014

Do Not Track HTTP headers.

Until today I had not heard of Do Not Track headers, referred to as DNT. I found out about it via news of Yahoo dropping support for it. After searching google I learnt that DNT is a HTTP header that can be turned on by users to tell websites not to track them. Once set it includes a DNT header with each HTTP request. If the user has said they do not want to be tracked it sets the headers value to 1. If they don't mind if they are tracked it sets it to 0 and if no option has been selected it sends it as null and does not send it with the request. Slight problem though because it is not a legal requirement for websites to honour the DNT requests. Much like the Apaches robots file they can simply ignore it and continue to track you if they choose :P
http://en.wikipedia.org/wiki/Do_Not_Track

After learning this I checked chromes settings, found the option and turned it on. In chrome it is located under: Settings, advanced settings, privacy.



After enabling it I configured chrome to go through burp suite so I could trap the request and see it for myself. Sure enough there was the DNT header set to 1.


Because sites can simply ignore the DNT flag an addon for Firefox and Chrome is being created called "Privacy Badger" and has been released in alpha. Privacy badger checks visited websites for any possible tracking cookies and blocks them. It can be found at:
https://www.eff.org/privacybadger

Email Scrapers and Spammers

Decided to write a web spider the other day and ended up playing with pythons "smtplib" library instead. These are some of the scripts I came up with.

Scrape a page for emails and send them an email.
This script will scrape a page you feed it for any emails and then send an email to any emails it finds. It uses googles SMTP servers so you need to input your email and password in the server login section. It first downloads the source code of the webpage using "urllib" and then parses it through the lxml parser using "Beautiful soup" and creates a BS object. It then uses a regex to filter out the emails and write them to a file. Next it does some cleanup on the email list and adds each email to an array. That array is used in the "to" field of the email. Next it creates the emails MIME headers to properly format the message and then sends the email. Bit of unnecessary repetition in this script with creating a list then adding it to an array but I did not start this script with this intention. Was just playing around and this is what came out :P. 

Example usage: ./auto_email.py http://www.example.com

#!/usr/bin/python

import urllib
from bs4 import BeautifulSoup
import sys
import re
import os
import smtplib
from email.MIMEText import MIMEText

###This script scrapes a webpage given as a command line argument for email adresses. It then
###Sends an email to each one.

def writeToFile(result):
emails = 0
file = open(emailLists, "a")
for line in result:
file.write(line + "\n")
emails +=1
file.close
print str(emails) + " results written to file"

def emailSpam(bs):
#create a email filter regex
email_re = re.compile(r'([\w\.,]+@[\w\.,]+\.\w+)')
global result
result = []
#search through bs using the email filter
result += email_re.findall(bs.text)
#write the results to file
writeToFile(result)

def sendEmails():
os.system("sort -u -o emailList emailList")
emailaddrs = []
for line in open(emailLists, "r").readlines():
        emailaddrs.append(line)

fromaddr = "anonymous@gmail.com"
toaddr = emailaddrs
TEXT = """Another multi message
with python"""
SUBJECT = "Test message"
message = 'Subject: %s\n\n%s' % (SUBJECT, TEXT)
SERVER = "smtp.gmail.com:587"

print "Connecting to mail server"
server = smtplib.SMTP(SERVER)
server.set_debuglevel(True)
server.ehlo()
print "Starting TTLS"
server.starttls()
print "TTLS started successfully"
print "logging in to GMAIL"
server.login("fakeemail@gmail.com", "fakepassword")
print "Sending emails"
server.sendmail(fromaddr, toaddr, message)
server.quit()
print "\n\nComplete"


#Get the html and parse it through BS-LXML
html = urllib.urlopen(sys.argv[1])

os.system("rm emailList")
print "Removed old list"

bs = BeautifulSoup(html.read(), "lxml")
global emailLists
emailLists = "emailList"

#Start the script
emailSpam(bs)
sendEmails()




Scrape a webpage for emails and write them to a file
Same as the above but it does not send the emails. It just writes them to a file for later use. 

#!/usr/bin/python

import urllib
from bs4 import BeautifulSoup
import sys
import mechanize
import re
import os
import smtplib
from email.MIMEText import MIMEText

###This script scrapes a webpage given as a command line argument for email adresses.

def writeToFile(result):
        emails = 0
        file = open(emailLists, "a")
        for line in result:
                file.write(line + "\n")
                emails +=1
        file.close
        print str(emails) + " results written to file"

def emailSpam(bs):
        #create a email filter regex
        email_re = re.compile(r'([\w\.,]+@[\w\.,]+\.\w+)')
        global result
        result = []
        #search through bs using the email filter
        result += email_re.findall(bs.text)
        #write the results to file
        writeToFile(result)

#Get the html and parse it through BS-LXML
html = urllib.urlopen(sys.argv[1])
bs = BeautifulSoup(html.read(), "lxml")
global emailLists
emailLists = "emailList"

#Start the script
emailSpam(bs)



Email a list of contacts.
This script takes an email list as input and emails each one. 

#!/usr/bin/python

#This bot takes the email list as command line argument. 

import smtplib
from email.MIMEText import MIMEText
import sys

lineCount = 0
emailaddrs = []
for line in open(sys.argv[1], "r").readlines():
        emailaddrs.append(line)
        lineCount += 1

fromaddr = "anonymous@gmail.com"
toaddr = emailaddrs
TEXT = """This is a test message"""
SUBJECT = "It works :D"
message = 'Subject: %s\n\n%s' % (SUBJECT, TEXT)
SERVER = "smtp.gmail.com:587"

print "Connecting to mail server"
server = smtplib.SMTP(SERVER)
server.set_debuglevel(True)
server.ehlo()
print "Starting TTLS"
server.starttls()
print "TTLS started successfully"
print "logging in to GMAIL"
server.login("fakeemail@gmail.com", "fakepassword")
print "Sending %s emails"%(str(lineCount))
server.sendmail(fromaddr, toaddr, message)
server.quit()
print "\n\nComplete"





Friday 2 May 2014

Bypassing encrypted session tokens using CBC bit flipping technique.

In the last few weeks I have been studying Web Application hacking. Yesterday and today have been focused on session management. After struggling to understand how CBC bit flipping works, it was real "holy sh*t" moment when it finally hit me. This technique is awesome and was a lot of fun working it out and then applying my knowledge on an actual vulnerable web app. This post will cover the technique and not the discovery of these tokens. I have only just learnt this so I am still unsure of the best techniques to reveal if a token is encrypted and ran through CBC.

I will be using the vulnerable web application called Mutillidae to demonstrate this attack. Mutillidae is a free vulnerable web app maintained by Jeremy Druin and I believe it was initially started by Adrian Crenshaw. Its purpose is to aid in teaching and learning pentesting. It has been very useful in aiding me in performing and practising various web app hacks. More info and download can be found at:
https://www.owasp.org/index.php/OWASP_Mutillidae_2_Project

What is a session token?
A session token is a string of data that is used to maintain a HTTP session between you and the web browser. HTTP itself cannot maintain a session so there needs to be some way for the server to know that you have logged in. Without maintaining your session you would have to sign into a web page every time you refreshed or visited a new page within the same site. Sessions tokens are similar to cookies although they are somewhat different in the way they are handled. Cookies and tokens both serve the same purpose. The vulnerabilities that occur with maintaining sessions is that if an attacker is able to steal your session token or cookie they can simply connect to the website using your token and bypass the authentication process. Another way is to simple guess the token. An example would be a token using your username as its data. An attacker would only need to replace his token with your username an login as you. One method of defence that is commonly used to protect tokens is to encrypt them so they are unreadable and cannot be guessed. 

What is CBC bit flipping?
CBC stands for cipher block chaining. Taken from Wiki:
Each block of plaintext is XORed with the previous ciphertext block before being encrypted. This way, each ciphertext block depends on all plaintext blocks processed up to that point. To make each message unique, an initialization vector must be used in the first block.

Say you want to use AES encryption for your tokens. If your message you want to encrypt is "password" then each time you encrypt the word "password" it will always result in the same encrypted output. This poses a security risk as an attacker can reverse engineer this by simply encrypting a list of words and then comparing them to the encrypted values thus revealing the token. The attacker can then create his own token, encrypt it and use it to login as another user. CBC is a way of randomizing the output of the encrypted value. It works by using an IV or initialization vector. The IV is a random value that is used against each block of your encrypted value. The first block of plain text is XORed with the IV and then that value is XORed with the next block and it keeps doing this until each block is XORed with the last one. It looks like this:


XOR is a simple technique of switching bits. It works by comparing the bits of two values. In our case the IV and the plain text for the first block and the ciphertext and the plain text from then on. If they are both 0 then it remains 0. If it is 0-1 then it becomes 1. if it is 1-1, it becomes 0. Simple enough. More info can be found at: http://en.wikipedia.org/wiki/XOR_cipher

Because reversing XOR essentially requires flipping the bit, this is how we can attack it. This attack does not decrypt the original encryption but simply alters the cipher-text so it is un-xored down the chain. Say your token is called "admin". It is encrypted and ran through CBC to come out like this. aaabbbccc999. This is now our token that maintains our session. Now say an attacker named john logs in and gets sent the token cccbbbccc1111. The attacker can flip the bits one at a time and send them to the server and monitor the results. ffcbbbccc1111 is sent to the server and his user name changes from john to *ohn. So now he knows the first bit of the token ff converts to *. He now finds the value of 'a' and sends the token 7bcbbbccc1111 and it responds with 'aohn'. The attacker now has the first part of the username he wishes to login as. He simple keeps flipping the bits of the token until he has one that converts to "admin". Say it has come out to 7bdc995465. He would then just send a request to the server using that token and be logged in as admin. 

Demonstration
In Mutilidae version 2.6.10 there is a page called User Privilege Level. This is designed to practise the CBC bit flip attack. It is located under: OWASP 2013, Broken authentication and session management, Privilege escalation, view user privileges. 

As you can see the goal of this challenge is to change the user and group to 000. The first thing we need is the IV. How do we get the IV with nothing presented to us? We need to use a proxy that sits in-between us and the server. I will be using burp suite for this. Burp suite is tool used to aid in web app pentesting. You need to configure your browser to go through the burp proxy. Setting up burp is out of scope for this post. Information on setting up burp can be found at:

Once burp is setup and intercepting traffic simply refresh the page and trap it in burp.


If you look closely you can see the IV has been sent along with the request. 
6bc24fc1ab650b25b4114e93a98f1eba
A useful tool included in burp suite is the repeater. The repeater keeps a copy of this request and lets us alter it and send it to the server multiple times without having to manually keep refreshing the page and capturing a new request. Right click and choose send to repeater. Also note down the IV in notepad or something. With the request in the repeater tab, navigate to the repeater tab and click GO.


In the response view of the repeater open the tab "Render". This allows us to review the rendered response of the request we just sent. This is where we can start flipping the bits in the IV. Note is sais User is root. I believe this is a bug as it should only say that when we set the User ID and Group ID to 000. Start by changing each bit of the IV to FF and monitoring the response keep doing so until you are able to change the output of the user and group field. Example:
FFc24fc1ab650b25b4114e93a98f1eba
We can see this altered the first part of the Application ID. The next test we flip the second bit:
FFFF4fc1ab650b25b4114e93a98f1eba
FFFFFFc1ab650b25b4114e93a98f1eba
FFFFFFFFab650b25b4114e93a98f1eba
FFFFFFFFFF650b25b4114e93a98f1eba
This is where we find our user ID field has changed. The value is now User ID : e00 
Ok so we know the bit we need to alter to change the part of the user ID field. Note this down as we will need it later. Continue flipping bits until you get to the part of the Group ID that needs changing. 
At this point we find the correct value:
FFFFFFFFFFFFFFFFb4114e93a98f1eba
Iv marked down those bits in the original IV and returned the rest to the original values:
6bc24fc1FF650bFFb4114e93a98f1eba




So we have found the bits we need to alter to change the correct parts of the User and Group ID. The next step is to alter them in a way that returns them as a zero. We see that the User ID we sent FF and it returned 'e'.The FF we sent was a hex value and it the 'e' is a literal so the 'e' needs to be converted to HEX. Use the burp decoder to decode 'e' into HEX(even though its hinted right next it :P) 'e' decodes to HEX value 65. Now we simply reverse to XOR by XORing FF with 65. Im using an online calculator to do this:
The XORed value returns HEX value 9a.

This gives us our cipher used. To get the literal value 0 needed in the User ID we get the HEX value of zero which is 30 and XOR it with 9a. The return HEX value is aa. Replace the original token with aa. it now looks like this:
6bc24fc1aa650bFFb4114e93a98f1eba
When sending this to the server we get:

To get the Group ID to zero we apply the same technique. Because FF is returning the weird '?' symbol I altered it until I had something better to work with. In this case I swapped FF with 22 so the group ID returned 6. Convert 6 to HEX(36) and XOR it with 22. This gives us HEX value 14. Now XOR the HEX value of 0(30) with 14. This gives us the final value of 24 Our final result looks like:
6bc24fc1aa650b24b4114e93a98f1eba. Sending this to the server we receive our desired User and Group ID. I believe this is where Mutilidae should inform us we are logged in as root. 
This technique requires a bit(see what i did there ;) ) to get used to. Essentially we are working backward and decrypting the cipher. When we have decrypted the cipher we can work forward to produce the desired outcome. We are NOT decrypting the actual encryption. We are only modifying the cipher so it is decrypted to the values we want. Its a case of XORing backwards then XORing forward.
When I first learnt this, I struggled to understand how we can use this is the real world. The book I am currently reading gave me a perfect example of when this may come in handy. Excerpt:

One application observed by the authors contained a file upload/download
function. Having uploaded a file, users were given a download link containing
a filename parameter. To prevent various attacks that manipulate file paths, the
application encrypted the filename within this parameter. However, if a user
requested a file that had been deleted, the application displayed an error mes-
sage showing the decrypted name of the requested file. This behavior could be
leveraged to find the plaintext value of any encrypted string used within the
application, including the values of session tokens. The session tokens were
found to contain various meaningful values in a structured format that was
vulnerable to the type of attack described in this section. Because these values
included textual usernames and application roles, rather than numeric identi-
fiers, it would have been extremely difficult to perform a successful exploit using
only blind bit flipping. However, using the filename decryptor function, it was
possible to systematically manipulate bits of a token while viewing the results.
This allowed the construction of a token that, when decrypted, specified a valid
user and administrative role, enabling full control of the application.

In this example the author found a section of a website that decrypted its encryption. This allowed them to decrypt their token. It might have looked something like this:
john:342_normal_user.
Using the bug in the webpage they would have altered it using the bit flipping technique so that to looked like:
admin:000_super_user