Thursday, January 30, 2014

CSRFin' USA! CSRF Mitigation Bypass with XSS

Cross Site Request Forgery

Cross Site Request Forgery (CSRF) is an attack where an attacker can trick a user's browser into performing actions on the attacker's behalf. This has the added benefit of taking advantage of the user's authentication. The archetypal example of CSRF is to imagine that if a bank customer wanted to transfer funds, they would have to visit a specific URL such as, http://bank.com/?transfer.php?to=hacker_acct&amount=1000. Then, all the attacker would have to do is trick people into clicking a link for that URL so that the victim's browser performs a GET and, if the victim happens to be logged into that bank, the victim will unknowingly transfer money to that attacker. The web application is going to assume that the user is in full control of its own actions and will execute the transfer. CSRF is about exploiting the trust that the web application has in the user's browser. You can read more about CSRF here.

CSRF Mitigation

The majority of CSRF mitigation strategies revolve around some sort of nonce being associated with the request being made. That can mean that instead of a dumb URL such as http://bank.com/?transfer.php?to=hacker_acct&amount=1000, you would have http://bank.com/usersession-1234?transfer.php?to=hacker_acct&amount=1000 so that the attacker could  not generate the link ahead of time. Another example of this when performing a POST is to add a hidden field set to a nonce. This token will get passed along when the user hits the submit button and the server will check that the nonce it set for that form is what was submitted. Like before, this nonce can't be pre-generated, and thus an attacker is unable to create a dumb link to trick users with. Here is what a CSRF token looks like:
That token prevents us from hard coding a POST to the URL since the value of that token should change each and every time the form is loaded.

Mitigating CSRF Mitigations

With these tokens and nonces making the URL or parameters unique, CSRF should pretty much be resolved because the attacker is not able to perform any actions right? Not quite. Let's review what XSS provides for us. XSS allows an attacker to run a script on a victim's browser. The victim's browser is going to trust that the script is safe and will execute, no questions asked. We can use an XSS vulnerability to execute code that will gather the necessary information to overcome the CSRF protections in place. In other words we use the XSS vulnerability to determine what the specific session information or token is, incorporate that into a CSRF attack, and proceed as a normal.

Putting It All Together

Let's go back to a previous post. What we had there was a XSS vulnerability in the body of an email. With that in mind, let's go looking around the web application a little more to see what we can find. Within the Advanced Options, we see that there is an option to configure the password reset question, answer, and a checkbox to enable the feature at all.
Let's go fill this out, hit submit, and trap the request with a Firefox plugin, named Tamper Data, that the browser makes so we know what we have to replicate. 

Here we see the POST that is made once we update these values and hit Save:

Tamper Data is showing us on the right hand side all of the parameters that are being passed to the URL. Of particular interest, we see that enabling the password reset question corresponds to the usepassresetting parameter having a value of checkbox and you can also see the URL encoded password reset question and the password reset answer. The other parameters are important as well and will play a part later.

The other important thing to realize is that another parameter that gets passed along is the id parameter that has a value of 333n487v6y1sJjJ0GFnzPsID8oKJBfmEZeyk20140130002922. If you log in and out a few times you will come to notice that this is probably a random value. I did not expend any time doing a statistical analysis with Burp to verify this but I assumed it was. This id parameter is what will stop us from being able to hardcode a POST to _processaccountoptions with usepassresetting set to checkbox and passresetanswer set to whatever we want. Fortunately, we can get around this thanks to the XSS vulnerability we have in our backpocket. 

The flow of the attack will go as follows, the victim opens an email with JavaScript embedded in the body of the email. This JavaScript snippet will call a piece of JavaScript on the attacker's server that will:
  1. Parse out the value of the id parameter in the URL of the victim's browser
  2. Use that id parameter value and complete the POST request to set the victim's password reset question.
Now, we will send an email to the victim with this embedded into the body of the email:


That will then call this piece of JavaScript that will be on the attacker's server:

This script will first grab the URL and then proceed to parse out the value of the id parameter by performing a substring. Next, it then calls the passwordReset function and that will piece together the parameters necessary to perform a proper POST to the _processaccountoptions URL. Notice that this sets the usepassresetting, passresetquestions, and passresetanswer.

This should be enough to bypass the randomly generated id and if everything works, when a user opens the malicious email they will unknowingly enable the password reset feature and set their password reset answer to whatever the attacker chose. This will then allow the attacker to set a user's password by using the password reset feature.

Thus when the user opens the email the attacker can:

  1. Go to the webmail login screen and click the Forgot your password? link 
  2. Enter the victim's email address
  3. And we should see that the victim will have their password reset question set to what we set it to be in our script, "Hacked via XSS"
  4. From there the attacker can input the answer to the question as, 'h4cked', and then set a new password for the user. Heck, you could probably do step 3 and 4 by extended the script to do another CSRF POST to save you the manual effort. 
I hope this post helped describe what CSRF is and what it allows you to do and just how powerful XSS can be and how its impact can be much more than just dumping cookies and throwing alert boxes.




Wednesday, January 22, 2014

Kriss Kross Site Scripting in Ability Mail Server - CVE-2013-6162

Cross Site Scripting

Cross Site Scripting (XSS) is a type of attack where an attacker can have a legitimate website or web application send a payload, usually JavaScript, to their user's browsers. The user's browser will then receive this payload and execute whatever it may be. Essentially, the attacker is taking advantage of the fact that the browser is going to trust that whatever the web application is sending is trustworthy and will execute it with no questions asked. Cross Site Request Forgery (CSRF) is the opposite of this where the web application will trust that whatever actions the user's web browser is requesting to perform are trustworthy and will execute them with no questions asked. We'll get to CSRF in a later post. You can read more about XSS and its various flavors here.

Anyways, XSS is often disregarded as low impact because the quintessential XSS proof of concept is usually throwing up an alert box. Big whoop. Well, not so fast...It is number three on OWASP's Top 10 (CSRF is number 8) so there's gotta be more to it. Let's dig in.

CVE-2013-6162 

CVE-2013-6162 is a XSS vulnerability I discovered in Ability Mail Server 3.1.1. It's a fairly simple XSS vulnerability to demonstrate, but I think it serves as a good example of what kind of impact XSS can have. After installing Ability Mail Server (AMS) and installing the webmail component of AMS, we created a victim account to do our testing on.

First things first, we will fuzz the various fields of an email. This can range from injecting JavaScript in the From, To, Subject, Date, etc. fields and seeing if you can trigger an alert box. Eventually we try injecting into the body of the email 

Once we run that script we log in with the victim account and view the email.

Success! We've been able to get the browser to execute JavaScript of our choosing.

Now, the normal XSS attack involves dumping the user's cookie and attempting to login as the user via a replay attack. Unfortunately, I didn't get a cookie when I attempted this. So, what else could we do? I never attempted using BeEF via XSS, only through the demo site so I decided to check it out. BeEF is a tool that you can use to execute commands against a victim's browser. The main stipulation is that the user must load the hook.js script which allows all of the magic. BeEF is a really great tool and you can read more about it here. I updated my proof of concept to load the hook.js script, fired up BeEF in Kali, and fired away.

Upon opening the email...

Sweet!

I have not had the opportunity to load BeEF via XSS before so this was a new wrinkle.

While this CVE deals with XSS and violating the trust that a browser has in a website, I was able to leverage this vulnerability into a CSRF attack. I'll detail that in another post.


Microcorruption - New Orleans

Microcorruption

Matasano and Square have created a fun little CTF that simulates a little embedded hardware hacking. They've simulated a debugger that is running on a lock that you access through your browser. The tutorial and the New Orleans challenge involve determining what the password is for a lock in order to move on.

New Orleans

This challenge starts off with a description of the lock with no real useful information in it. 

So off we go into the debugger! 

If you run the program, it asks you to enter a password. Since we don't know what it is we can enter random text and see how the program processes it. 

Entering in some string like, "test", and continuing execution we are ushered quickly out of the program. :(

Bugger, now we'll have to step through and see what it may be doing. Looking at main we see a few interesting items...

The check_password and get_password functions might be worth looking into. The check_password function looks like this:

Before this function is called, it should be mentioned that r15 holds the location in memory of the password that you entered in. What this function looks like it does is compare the string held at r13, which is assigned from r15, to the memory location at 0x2400. Looking in the Live Memory Dump section for whats held at 0x2400 we see this:

At this point we can take a wild guess that the first password is p:J>>V`

Success!

This is a pretty fun CTF. I'm looking forward to checking out the other challenges. I'll try and write them up as I go along, but I stink so I'm guessing I'll only be able to get the first challenge =P

Monday, January 20, 2014

Fuzzing vulnserver with Python

A request from the corelan.be forums was made asking about creating a custom fuzzer using Python. It's simple enough, but for posterity let's go through this process.

Fuzzing

So, if we examined the kinds of input Peach was supplying to vulnserver when we fuzzed the HTER command in a previous post we see that it basically threw a bunch of junk input of varying sizes. In a very bad generalization, it's increasing the amount of junk to determine if it crashes the program. Fuzzing is a lot more complicated and nuanced than this obviously so check out this book or these links for further reading. 

Using Python to Fuzz

OK, but lets try and roll our own fuzzer in Python for the HTER command. If we recall the StateModel we created in our Peach Pit, the format of the HTER protocol was:
  1. Receive some data
  2. Send the HTER command with our input
  3. Receive some data

With this in mind, we know enough to go about creating our fuzzer in Python. The general flow is going to be:
  1. Create a connection to vulnserver
  2. Receive the banner for vulnserver, i.e. "Welcome to Vulnerable Server..."
  3. Send our fuzzed data in ever increasing amounts, i.e. "HTER <fuzzed input>
  4. Receive the response from vulnserver, i.e. "HTER RUNNING FINE"
  5. Increase the amount of fuzzed input
  6. Close the connection to vulnerserver
  7. Go back to step 1
  8. If we can't connect to vulnserver then we can guess that the previous input crashed vulnserver and we can print a message
Here's what this looks like in code:

Here's what the output looks like when running this script against an instance of vulnserver:

And we are greeted with this popup as well:

So we have a good indication that 2040 As will result in vulnserver crashing. Let's make a quick proof of concept from our fuzzer to test if 2040 As will crash vulnserver.

Not that complicated, but when we run it we get the popup that vulnserver.exe has crashed so we're on to something.

Viewing the Crash Under a Debugger

Just for fun, let's run vulnserver under Immunity Debugger and see what's going on under the covers when we run our proof of concept. You can get Immunity Debugger from here.
First we'll start Immunity. Then File > Open and select vulnserver.exe and then click the Open button. This spin up vulnserver, but pause it right before it hits the Program entry point. You should see on the bottom right hand side a yellow text box that says "Paused". Hit F9 or go to Debug > Run to start the program. That yellow text box saying "Paused" should now say "Running". Great, now we have vulnserver up and running so we can throw our proof of concept at it. Hopefully we should see some registers light up with As when we run it.
Once we execute our proof of concept we see at the bottom of Immunity that we've hit an exception.

And if we look at our registers we see that this particular crash didn't reveal anything too interesting.

It looks like we were able to overwrite most of EBP, but we didn't get a hold of anything else =/. Ohh well, from here we could start throwing 2030 As and so on to see if we get a better result.

Hope this helped.

Tuesday, January 14, 2014

Fuzzing Vulnserver with Peach 3

Vulnserver

Vulnserver is a purposely vulnerable application that is meant for practicing exploitation written by Stephan Bradshaw. It's basically a server that accepts TCP connections and takes in random input that will result in various buffer overflows and SEH overwrites. It's a pretty good way of learning how buffer overflows and SEH overwrites work in a manageable setting. There are also lots of good walkthroughs on how to achieve code execution on Bradshaw's blog and on Infosecinstitute. There's even a good walkthrough on fuzzing Vulnserver with Peach 2.x by Dejan Lukan. I probably wouldn't have even bothered with this posting if it wasn't for the fact that Peach 3.0 was a complete rewrite so some of the syntax in Lukan's example is a tad out of date. 

Peach

Peach is a fuzzer that supports generational and mutation based fuzzing. It uses XML files to determine the structure of the protocol you are trying to fuzz and how it should go about performing the actual fuzzing, i.e. make a network connection or output to a file. I've been meaning to practice fuzzing with a fuzzer like Peach or Spike. I ultimately settled on Peach because from the looks of it it has a more active support community so if I ran in to issues it could be easier to find answers. 

Setting Up

After downloading peach from here, downloading Vulnserver from here, netcat for Windows from here (with or without the -e option), and installing the Windbg for Windows 7 Standalong Debugging Tools (also for Windows XP) from here we are more or less ready to go. 

First we fire up a command prompt and execute vulnserver. By default it will listen on port 9999, but if you give it a port number it will listen on that instead. 


Next, we'll open up another command prompt and connect to it with netcat on port 9999 and poke around the application. Typing, 'HELP', we are presented with a list of commands that vulnserver supports. The exact meaning of these commands are not important. They are just there to provide different ways of supplying input that can crash the application.

If you go ahead and type a command and provide some input you should get a response back saying that the input was received fine. Here are a few examples of interaction with vulnserver:

So it appears that the general protocol used by vulnserver is: [command] [input] [newline]. This should be enough knowledge to start making a Peach Pit and start fuzzing vulnserver.

Peach Pit

Peach Pits have the general form of Data Models, followed by State Models, followed by Agents, followed by Tests.

Data Model

The Data Model describes the format of data that Peach can accept as input or that it should use when attempting to fuzz something. Fortunately our format is fairly simple with just a fixed command, a space, a string that is fuzzable, a carriage return character, and a new line character. More complex protocols may require you to have more fields, numbers and strings mixed, fields that are dependent on the size of other fields, etc. 
Something to note is that you can have multiple Data Models in a Peach Pit. Although in our case we will only focus on one command, you could have a Data Model for each command in vulnserver in your Peach Pit.

State Model

Next up we have the State Model. The State Model basically tells Peach how to behave so that it cooperates with the protocol is it trying to fuzz. The State Model will consist one or more States which are comprised of one or more Actions which lay out the exact steps that Peach should take when fuzzing. Does Peach need to accept output from a network connection before supplying input? Your actions will have to model that. Not only that, but if you are accepting output, you need to tell Peach what that output will look like in the form of a Data Model. If you are fuzzing a file format, you may have to have actions that tell Peach to open, write fuzzed data to, and close files. Again, fortunately for us vulnserver is pretty basic so our State Model will just consist of an input action to accept the initial welcome message, and output action to send our fuzzed data model, and another input action to receive the confirmation output from vulnserver if it hasn't crashed.

Agents

While fuzzing, run one of the things you will have to do is start Peach in agent mode. This agent will run the program that you are trying to fuzz and a debugger to monitor the program. It will also be responsible for detecting crashes and logging those instances. Agents can be a tricky thing to configure. 

Tests

Finally, there are Tests. A Test will kind of bring everything together and describe how you want your fuzzing run to proceed. Here you get to decide which Agent and State Model should be used. There also two other important things you determine in a Test as well. The Publisher tells Peach in what manner it will input and output with the program. Are we communicating via a file? TCP? UDP? You will specify that in a Publisher. The Logger is where you tell Peach to place the logs that it will generate.

HTER Example

Here is what a Peach Pit for the HTER command might look like (modified from Lukan's tutorial):
As a short run down here is a summary of what we have. First there is a Data Model named DataHTER which basically describes how to will send out HTER command to vulnserver. We will always send the string "HTER " (observe the space!), then a string which we will let Peach decide what that should be, followed by a carriage return and a new line.

Next, the StateHTER State Model says we will accept output from vulnserver that will look like the DataResponse Data Model (which we haven't defined yet!), send a DataHTER Data Model, and then accept more output that looks like a DataResponse Data Model.

Now we define the DataResponse DataModel. This is merely a string. Nothing fancy.

The Agent comes next. Here we indicate that Peach fuzzer will connect to the Peach Agent at 127.0.0.1 on TCP port 9001. We also say that the Monitor for this Agent will be a WindowsDebugger and we indicate that the command line program to run is vulnserver.exe and where it can be found. Then we tell the Monitor where it can find WinDbg.

Test is last and here we say that we want to use the Agent named "RemoteAgent", perform a test using the protocol described in the State Model named "StateHTER", that we should publish the fuzzed output using the TcpClient on IP address 127.0.0.1 at TCP port 9999. Finally we say that we should record the findings in a subfolder named "Logs".

Whew!

Fuzzing

Now comes the fun part. First we will fire up a Peach Agent and tell it to use the TCP channel. The Peach Agent will wait for instructions from a Peach fuzzer and ultimately be responsible for running vulnserver each and every time and detect if a crash occurred.

Next, the moment of truth, we will run Peach, pass in our Peach Pit, and the name of the test we want to run. 


Hopefully every once in a while you should see output from your Peach command shell that looks similar to this:

This is an indication that Peach sent a value that caused a crash. Peach should then save off the same input for you look at later. Peach can take a while to run through its test cases so you can feel free to stop Peach whenever you feel like or leave it running for as long as you care.

Examining the Output

Let's take a closer look at the input that caused the crash at iteration 171. From where you ran Peach, you should have a folder named Logs. Inside of that you should have a folder that was created from your run and inside of that you should have a folder named Faults. This folder will store the runs that caused a crash. One of the nice feature of Peach is that when it runs a program using WinDbg, it will automatically load a module from Microsoft, MSEC Debugger Extensions, that will make an attempt to determine if the crash is exploitable or not. MSEC is currently on 1.6 but Peach only comes with 1.0.6 so hopefully that will change in the future. 
We are in luck because in our Faults folder we see a folder named, EXPLOITABLE_0x264d5172_0x00000000. Opening up that folder we see yet another folder named after the iteration that caused the crash, 171. Inside the 171 folder there are several text files. Probably, the two most interesting ones in this cause will be WindowsDebugEngine_StackTrace.txt and action_2_Output_Unknown Action 2.txt. WindowsDebugEngine_StackTrace.txt is, not surprisingly, a stack trace of vulnserver at the time of the crash. It's worth it to take a look just to see what the state of the registers are to see if we could potentially have control over any of them. The other interesting file, action_2_Output_Unknown Action 2.txt, is what Peach sent to vulnserver. The output and action 2 part of the title correspond to the StateHTER State Model that we specified in TestHTER in our Peach Pit.

Now we know that sending HTER followed by 9,526 As will crash vulnserver in a potentially exploitable way. 

Hooray! 

Can we do better and turn this in to remote code execution? Maybe I'll write this up if there's interest in this, but there a bunch of tutorials that explain how to do this.