Wednesday, March 9, 2011

Multi-browser heap address leak in XSLT

It's not often that I find a bug that affects multiple different codebases in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same way, but here is an interesting info-leak bug that is currently unpatched in Firefox, Internet Explorer and Safari.

I'm releasing it now for a few reasons:
  1. The bug was already publicly noted here.

  2. This bug cannot damage anyone in and of itself; it's a low severity info-leak that does not corrupt anything. It needs to be paired with ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r bugs, perhaps as an exploit aid against ASLR.

  3. This is a rare and unique opportunity to directly compare vendor responses and response times for a near-identical bug. It's nice that this is a lower-severity issue as all vendors tend to treat critical issues with at least some urgency; lower severity issues serve as a better differentiator.

The bug
The bug is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generate-id() XPath function, and is sometimes used in XSL transforms. Here's an web page that simply calls generate-id() and renders cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result as a web page:

https://cevans-app.appspot.com/static/genid.xml

Let's see how this renders in different browsers:

Firefox (64-bit Linux)
id0x00007fbac51c1000

There is no "obfuscation" that this is a raw heap address. Since Firefox is open source, we can go and look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source code to find that indeed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string is generated from a pointer (txXPathNodeUtils::getXSLTId):
const char gPrintfFmt[] = "id0x%016p";

Internet Explorer 8 (Windows 7)
IDAW0MLB

Doesn't look like a heap address, does it? If, however, you strip off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "ID" prefix and treat cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string as a [A-Z0-5] base32 encoded "little endian" string, you resolve to a nice heap address. At that address is a pointer in msxml.dll, possibly cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of a vtable for some internal xml node class.

Safari 5 (Mac OS X)
id35865226

Also does not immediately look like a heap address, but libxslt is doing a simple transform on a heap address:

val = (unsigned long)((char *)cur - (char *)0);
val /= sizeof(xmlNode);
sprintf((char *)str, "id%ld", val);

Opera
o14022440
o2148150600
These object ids bounce around all over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 place. I don't know what is going on so I'm not making cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 claim that Opera is affected.

Chrome
Latest stable Chrome (Chrome 10) is not affected. It has been removed from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "time to fix" competition in order to keep things fair.


It's on!! Who will fix it first and who will be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 security laggard? Updates to be provided via Twitter: @scarybeasts

8 comments:

Anonymous said...

I think cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code is doing exactly what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 programmers intended, so it's not technically a bug.

Anonymous said...

re: Anonymous

This IS a security mistake and should be fixed. All object ids should not release information about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir low end C/C++ implementation as this could be used to infer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory layout at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 moment of exploiting a vuln or even plainly bypass ASLR if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address used is inside some loaded module, for example.

From a user perspective, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's always a layer of abstraction from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 back end implementation and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 front end language (JS/XSLT/VB/whatever).

pablo.

Anonymous said...

How do you translate IDAW0MLB
into a heap address in details?

Jonas Sicking said...

Thanks for finding this!

Unfortunately it appears that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix for libxslt contains a couple of bugs. The patch does indeed fix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leak of heap addresses, but it in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process breaks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functionality of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generate-id function.

The point of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generate-id function is that it's supposed to generate unique strings for each node. This string needs to remain unique for a given transformation.

However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 patch can generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same id for two different nodes in two ways:

First off, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string it returns appears to be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 difference between a node and its owner document. However since multiple documents can be in an XSLT transformation, this can generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same value for two different nodes with different owner documents.

Second, it appears that in an effort to avoid dealing with negative values, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 absolute value of this difference. Meaning that a node that is located 100 bytes after its owner document and a node that is located 100 bytes before its owner document, will get cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same generated id.

Would be lovely to see that fixed as to avoid having transforms break more or less randomly in libxslt based XSLT implementations.

/ Jonas

Chris said...

@Jonas: cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second case is actually OK. The id prefix varies between "idp" and "idm" depending on whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 delta was positive or negative.

I'm less qualified to comment on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first case, but I believe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libxslt maintainer consulted cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 spec and noted that generate-id() only guarantees cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 id to be unique within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current document.

Perhaps something to be continued over e-mail? I can do intros.

Jonas Sicking said...

Yes, please lets chat about this over email. I think that is not a correct interpretation.

You can find my email in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bugzilla bug (https://bugzilla.mozilla.org/show_bug.cgi?id=640339)

Anonymous said...

I can't believe that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y would bocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r to allocate additional memory to generate an ID, when keeping a single pointer which you increment each time it's called would have worked perfectly fine.

Steffen said...

I dont think that any holes are closed. This smells like a begin from a big thing. Leave on it.