Thursday, October 15, 2009

A couple of unicode issues on PHP and Firefox

Well, here I am developing ACS, finding that this project resembles at some degree the creation of a browser.. but anyway, it's close to a working beta (yay!).

In any case, a couple of bugs came to my attention, some of them are public, some of them are not.

First of all, I want to describe the PHP vulnerability I made public on my presentation with David Lindsay, at Blackhat USA 2009, that apparently only Chris Weber, Giorgio Maone (creator of NoScript), Mario Heiderich (creator of PHP-IDS) and the Acunetix security team have realized the danger of it.

It has been reported, well, more than enough times to the PHP team (I made another attempt today, hoping this will get fixed in some time soon.. if at all). This issue affects all PHP versions Mario Heiderich and me could test, and endangers practically all PHP programs that use the utf8_decode() function for decoding (as recommended by OWASP guidelines).

The disclosure timeline follows:
* Reported by May 11 2009
* Discovered by June 19 2009
* Discovered by Giorgio Maone / Eduardo Vela: July 14 2009
* Reported and Fixed on PHPIDS: July 14 2009
* Microsoft notified of a XSS Filter bypass: July 14 2009
* Fixed XSS Filter bypass on NoScript 1.9.6:  July 20 2009
* Vulnerability disclosed on BlackHat USA 2009: July 29 2009
* Added signature to Acunetix WVS: August 14 2009
* Re-reported by September 27 2009
* Vendor claims it was fixed on 5.2.11: September 29 2009
* Re-re-reported by after checking 5.2.11: October 16 2009
* Published October 16 2009

You can check the bug here:

In reality there are several vulns in just a couple of lines, so I'll describe them here:
1.- Overlong UTF-8:
As REQUIRED by UNICODE 3.1, and noted in the Unicode Technical Report #36, UTF-8 is forbidden to interpretate a character's non-shortest form.

VULN: PHP makes no checks whatsoever on this matter.

Why is this a vulnerability?

A filter (such as addslashes, htmlentities, escapeshellarg, etc.) will NOT be able to detect&escape such byte sequences, and so an application that relies on them for security checks wont be protected at all. Because it allows an attacker to encode "dangerous" chars, such as ', ", <, ;, &, \0 in different ways:

' = %27 = %c0%a7 = %e0%80%a7 = %f0%80%80%a7
" = %22 = %c0%a2 = %e0%80%a2 = %f0%80%80%a2
< = %3c = %c0%bc = %e0%80%bc = %f0%80%80%bc
; = %3b = %c0%bb = %e0%80%bb = %f0%80%80%bb
& = %26 = %c0%a6 = %e0%80%a6 = %f0%80%80%a6
\0= % 00 = %c0%80 = %e0%80%80 = %f0%80%80%80

Use hackvertor to generate them.

Enabling attacks on systems that use addslashes for example (but almost all encoding functions would be vulnerable):

// add slashes!
foreach($_GET as $k=>$v)$_GET[$k]=addslashes("$v");

//  .... some code ...

// $name is encoded in utf8
mysql_query("SELECT * FROM table WHERE name='$name';");


2.- Ill formed sequences:
As REQUIRED by UNICODE 3.0, and noted in the Unicode Technical Report #36, if a leading byte is followed by an invalid successor byte, then it should NOT consume it.

VULN: PHP will consume invalid bytes.

Why is this a vulnerability?

It will allow an attacker to "eat" controll chars. For example:

// htmlentities
foreach($_GET as $k=>$v)$_GET[$k]=htmlentities("$v",ENT_QUOTES);

//  ... some code ...


//  ... some code ...

$profileImage="<img alt=\"Photo of $name\" src=\"http://$url\" />";

// ... some code ...
echo utf8_decode($profileImage);

A request such as:


Will execute the code "alert(1)" when the page loads.

Note that htmlpurifier does a utf8_decode function call at the end of the decoding, BUT they are safe because of a pre-encoding made by htmlpurifier.. other codes that do the same wont be so lucky.

Bogdan Calin from Acunetix WVS described a couple of other potential attack scenarios:

Where an attacker could fool the filter by doing a request like:


Where an attacker could fool the filter by doing a request like:

3.- Integer overflow:
Unsigned short has a size of 16 bits (2 bytes), that is UNCAPABLE of storing unicode characters of 21 bits, and represented on UTF with 4 bytes (1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx). PHP attempts to sum a 21 bits value to a 16 bits-size variable, and then makes no checks on the value.

The affected code follows:

//  php/ext/xml/xml.c#558
PHPAPI char *xml_utf8_decode(    //  ...
    int pos = len;
    char *newbuf = emallo    //  ...
    unsigned short c;          // sizeof(unsigned short)==16 bits
    char (*decoder)(unsig    //  ...
    xml_encoding *enc = x    //  ...
//  ...
//  #580
    c = (unsigned char)(*s);
    if (c >= 0xf0) {         /* four bytes encoded, 21 bits */
        if(pos-4 >= 0) {
            c = ((s[0]&7)<<18) | ((s[1]&63)<<12) | ((s[2]&63)<<6) | (s[3]&63);
        } else {
            c = '?';   
        s += 4;
        pos -= 4;
//  ...

The relevant part of the code is of course, the declaration of c as an unsigned int, the comment specifing that the char is 21 bits, and this:
x= ((s[0]&7)<<18) | ...

s[0]&7<<18 means it will move 3 bits, 18 bits to the right. As we noted before.. c's size is only 16 bits.
(xxxx xxxx & 0000 0111) << 18

Also, this part:
...  ((s[1]&63)<<12) | ...

s[1]&63<<12 means it will move 6 bits, 12 bits to the right. So, 2 bits are going to be lost.
(xxxx xxxx & 0011 1111) << 12

This allows us to make something even more interesting.

Code like this:

%FF%F0%40%FC that is invalid unicode, overlong, and all you want (definatelly NOT valid), will be casted as a "lower than" simbol (<).

This besides the already mentioned problems, and the possibility of bypassing quite a lot of WAFs and Filters.. demonstrate the problem of a bad unicode implementation on PHP.

I hope the PHP development team acknowledges all this issues that have been reported before, and were explained some months ago on Blackhat USA (and the developers were noticed to check the ppt more than once), and now are explained yet another time.

This was fixed on 5.2.11 :) on my birthday!! Sept 17

Anyway.. that's not all, now to finish this post I want to publish a overlong utf-8 exception on Firefox (actually, Mozilla's).

The firefox one

Firefox is supposed to consider the non-shortest form exception (point #1 in the PHP vulnerabilities), and section 3.1 of the Unicode Technical Report #36 but apparently there's a flaw on it. This is specially problematic for the reasons that an overlong unicode sequence not taken into consideration may allow several types of filter bypasses.

Anyway, the severity of this vulnerability is not as high as the PHP ones, but is worth mentioning. The following non-shortest form for the char U+1000:
0xF0 0x81 0x80 0x80

is allowed, as well as the correct shortest form:
0xE1 0x80 0x80

Note that this problem is only present on the 4 bytes representation.

You can track this bug at:

Anyway, that's all! Thanks for your time :)


Tuesday, August 04, 2009

Our Favorite XSS Filters and how to Attack them

So well, Black Hat 2009 and DEFCON 17 are over now, and on Black Hat I presented twice, so I want to
do a quick recap.

If you asisted to them, I would appreciate any feedback, since the blackhat's feedback system about
the passport stuff is like.. not-public, so its completely useless for me.

So, if anyone want's to give feedback, you can use the comments or send me an email at

David Lindsay also made a nice write up about the presentation in here:

You can get our slides from here:

I don't know if the CNN and bugs have been fixed, but they did worked at the stage (we made
a live-demo on how to bypass the IE8 xss filter), and well there's an errata on the NoScript section.

There was a fix I didnt tested regarding the same origin exception, so now instead of using:


Since we dont really need TinyURL, it was just an extra, but well, it makes sense for it to get fixed.

And also, the DoS & pwn for NoScript well, apparently because of something related to ABE, now noscript will absolutely kill your browser.  Upgrade to latest NoScript to be protected against the PoC of the presentation.

So, in the talk, david presented about the not-so-filtered html/js tricks we use, the unicode part was a
quick (very quick) recap since Chris Weber was going to have a cool presentation about Unicode the next
day (and it was awesome!!!) but anyway, regarding the unicode section, I made a quick demo on a vuln on
PHP's 4, 5 and 6 utf8_decode function that allows an attacker to do cool filter bypasses.

The PHP-IDS section, I'm not sure if Mario has fixed it, but my bypass was fixed.

Besides that, if you are going to use PHP-IDS, you can be sure that thornmaker and all the slackers crew
is gonna be there to break it and report it waay before a real-life attacker can bypass it, just remember
to keep it updated.

So, the talk was cool, I actually thought I wasn't going to finish on time so I was talking very fast, and
in a matter of fact I actually talked so fast that I actually finished 10 minutes before time.

So well, after that, I spoke with a couple of people about the presentation, and I got quite a lot of biz
cards (I didn't realized untill I got to the hotel and emptied my pockets.. I actually can't rememer to who
all those cards belong to), so if I told you I was going to get back to you later, you should probably send
me an email ( since I probably wont recognize your name in your card (my memory sucks!).

So well, the second day I had another talk, that was a solution Im working on, that sort of competes with
Mozilla CSP (could help as a transition to CSP) called ACS -  Active Content Signatures, that will implement
security measures for protecting against XSS on the client-side without the need of an addon on your browser.

I plan to implement some of NoScript features, as well as IE8 XSS Filter, and CSP, so I'll try just to get
the best of the best stuff in there. Inlcuding a JS sandbox that is being made by Gareth Hayes and that sort
of combines the best of Google Caja and Facebook JS sandbox but all in the client side, so you dont need to
do ANYTHING at all in the server :).

The second talk was an epic fail, I lost my document (it was on the Downloads folder, duh!) so there was
like a 5 to 10 minutes gap of me setting up my computer and not-finding the doc..

Thankfully it was a breakout session so it wasn't taped haha, anyway, my audience was small but very
speciallized, the Mozilla security squid and Mozilla securinator were there, as well as david ross, the
author of the super-IE8 XSS filter, a couple of friends and some other people.. The q&a at the end was
very cool :).

I haven't published the details of the .doc of ACS since well, it is still in an early stage but if you
are interested I will send you a draft. I am planing to present it during this month, and I will let you
all guys know in this blog, together with a nice demo.

The HTML Parser of ACS together with the JavaScript sandbox (JSReg) of Gareth can be tried at:

If you can hack it, please do it (and let me now =D). There's a thread about it here:,29259

Also, I want to state that I want to do:
    ./ -h -p /rsnake -p /id

So well, blackhat was a lot of fun, and actually I wasn't planning to stay for defcon, but with a fast
flight change and a lot of luck, I was able to stay more time, and go to defcon.

I want to say that DEFCON is waaaaaaaaaaay too fun, I didn't know it was so cool! BlackHat is like for
CSOs, CTOs, etc.. so vendors were like giving away gifts to everyone so they will buy their stuff, and
well, the talks were more interesting, but anyway, defcon rocks.

The 2wire talk that my friend hakim gave was very cool, we went to war driving in a limousine the night
before, that was fun as hell haha.

It was nice to meet all those slackers in blackhat/defcon, I'm sorry for all those casinos in the strip
that got their wifi-paying system completely bypassed by a very skilled slacker (whose identity prefers to
be kept private), but the hotels include bellagio, mirage, paris, caesars palace, circus circus, riviera
and well probably every hotel in the world that uses COX for providing the service (maybe also Lodgenet).

Ah btw, regarding the last post of Google Analytics, I want to show something I think is very cool. To make
impossible to a user to logout and/or login to any google service (gmail/google reader/google analytics/

If you readed all this post and you are not following me on twitter, then well, there it is!

When your victim gets a "bad request" that means, "you win". Google knows about this since like 4 or 5 months
ago.. and it's still unfixed. If one day you can't access your google account, or can't logout, try deleting
all your cookies.. And either use noscript and mark as untrusted, or point in your hosts
fike to (and if you are a system admin that is not using google analytics you
should probably also do the same, since all websites in the world that use google analytics are vulnerable
to this attack, and you are protecting your user's security AND privacy by doing so..).


PS. I made this post on notepad so its probably weird on blogspot.

Saturday, April 18, 2009

How to use Google Analytics to DoS a client from some website.

So, right.. I was trying to read some stuff about problems sharing my wired connection of my linux laptop to another windows laptop via wireless, but one of the links was on, and for some reason it's blocked on China (yeah, I'm living on China now =D). So, I decided to go to a friend's website to read the webpage, but... suddenly, there was an error..

Bad Request
Your browser sent a request that this server could not understand.

Size of a request header field exceeds server limit.


The reason of the error is unknown, but that's not important, what is important is that I realized that with a big enough cookie (8190 bytes aprox) we can DoS someone from entering a webpage. (With a 400 HTTP Response status code on Apache, a 413 on some google services, and on some websites an infinite loop because the big cookies delete session cookies).

The reason we would like to block from accessing a server is not really important, what is important is that being able to block them out is dangerous.

Anyway.. we need to set cookies, and this is good enough for a lot of attacks (like no-ip domains, shared subdomains like blogspot , browsers that allow top level domain cookies, second level domains like , etc..), but I really wanted to do something more cool.. so I started thinking, how to set cookies on clients.

And the "how", as the reader may deduce from the title of this blogspot is using Google Analytics. I've been researching Google Analytics cookies for some time now, so I sort-of know how they work. And I know pretty good that the google's implementation allows an attacker to add anything in some cookies.

So well, one of those cookies is the referer. This is true for "search result - organic referers", like for example, a Google search. The catch is that the detection on google's service is very bad, and we can fool it to think we are a google search result by doing:

So, you can guess.. if search-term is big enough we can hack the world.

Anyway, there's a catch. You can't set such a big cookie. The limit aparently is 4192 bytes. So.. what you have to do is control 2 cookies.

The other cookie we are going to be using is GASO (Google Analytics Site Overlay), its trigered by the content on

And well, the google analytics code will set a cookie called GASO to somevalue

With both vectors we can now set very big cookies! and with those cookies we can disable access to lot of websites to anyone with just a link (or an iframe if you want to improve the stealthness of the attack).

Twitter PoC:

If you use twitter over SSL...

To lock you out of all blogs:
Try your favorite Google Analytics powered websites :D


GASO limit

SEARCH referer limit

Monday, January 19, 2009

Oracle Containers For Java Directory Traversal (OC4J) Oracle Application Server 10g ( Oracle HTTP Server

Server Version Info: Oracle-Application-Server-10g/ Oracle-HTTP-Server
PoC: http://OC4J/web-app/foobar/%c0%ae%c0%ae/WEB-INF/web.xml
Explaination: The "%c0%ae%c0%ae" is interpreted as: ".." because on Java's side: "%c0%ae" is interpreted as: "\uC0AE" that get's casted to an ASCII-LOW char, that is: ".".

You can read dangerous configuration information including passwords, users, paths, etc..
Discovered: 8/16/08
Vendor contacted: 8/16/08
Vendor response: 8/18/08
Vendor reproduced the issue: 9/10/08
Vendor last contact: 9/30/08
Public Disclosure: 1/19/09

Oracle security bug id: 7391479

For more information contact Oracle Security Team:

I really wanted to give a link to a patch, but I think it's better if this is known by sysadmins so they can filter this using an IDS.