Archive for the ‘New Findings’ Category
Mike Tracy | June 26th, 2008 | Filed Under: Defenses, Malware, New Findings
1.
Some of my
favorite
reads (there are
others) have recently written about about Scrawlr and some of what I
have read has been critical. Critical enough? Depending on your level of
pedantry with respect to webapp security and/or free software, probably
not.
Stop that. Right now. Overlook the limitations of the tool that was
released, realize that this is a closely targeted thing designed to help
alleviate a specific problem. Go back and think a little harder about
what is going on and why this is actually A Good Thing(tm).
This scanner, released as part of the advisory, is specifically designed
to help people who run websites that have been targeted by this ongoing
and massive SQL injection attack shore things up. The tool has
limitations. Quoted from a text file included with the Scrawlr package:
This is a free tool and is intended to find SQL Injection
vulnerabilities on pages that hackers can discover using a simple
crawler or google query. This application mimics a search engine
crawler and lacks the advanced crawling and auditing features of tools
such as WebInspect, DevInspect, QAInspect, and AMP. Thus Scrawlr will
only find SQL Injection vulnerabilities on GET Parameters; Scrawler will
not submit forms, nor audit them. The list below summarizes the
limitations:
- 1500 Max Crawled URLs
- No Script parsing during crawl
- No Flash parsing during crawl
- No form submissions during crawl (No POST Parameters)
- Only simple proxy support
- No authentication or login functionality
- Does not check for blind SQL injection
The scanner is built to look for things being indexed by search
engines. If those sites are fixed, 99.999% of the problem should go
away.
Trying to compare Scrawlr to a full blown SQL Injection scanning tool is
like comparing a letter opener to a Swiss Army Knife. Sure, you can do
other things with a letter opener (and some of you probably want to slit
my throat for that simile. That’s fine, use the knife) —- but its stated
purpose is to open letters.
2.
The limitations aren’t that bad. Take the biggest one, authentication. I
tried it. For the vast majority of sites, “authentication” means “HTTP
forms that set cookies”. For those types of sites, it was easy to get
the tool to operate against sites “post authentication”. (I didn’t try
for basic/ntlm/digest —- I don’t have a ready test subject. I’d be
surprised if it worked.)
Using burp suite do the following:
- Login to the application using a web browser
- record the Cookie: header
- in burp go into the Proxy -> Options tabs
- go to the “match and replace” section
- add a new header
- Type: request-header
- Match: ^Accept.*$
- Replace: Cookie:
- point Scrawlr at your running proxy
Basically, just replacing the Accept: */* header that Scrawlr sends
with a Cookie header.
Yay! A free tool that people can use to see if their sites are
vulnerable to mischief. Plus! A free code scanner and a free sort of
maybe web application firewall to help them protect themselves. Your
old ASP sites are now safe from all this ruckus.
3.
I spent some time talking about this with colleagues (colleague n.
drinking buddy) at ChiSec last night [if you weren’t there it was a
blast and you should come to the next one -ed.] and as much as I love
the idea behind this, consternation is bubbling beneath the surface.
What I’m having trouble understanding are the motivations of Microsoft
and HP and their estimation of how effective this will actually be.
This is either Defense In Depth’s red-headed stepchild cum marketing
ploy or… Not sure I actually see an “or”. Half-baked code analyzer
(ok I don’t really know that but…)? Check. Web Application
Firewall Lite? Check. Hey! Get the guys at SPI to throw in a
cripple-ware SQL injection scanner and we’re all set to at least appear
like we are trying in some way to maybe have a chance at helping a
person or two.
Great!
I want a count of the owners of target audience websites who actually
read the advisory, understand it, realize they are affected and then
actually use any of the schwag provided to help them solve their
problems.
Microsoft seems like a good egg for going to all this trouble and HP
gets their name on it. Maybe people will come sniffing around for a
“real” security tool or two. Humbug I say!
In the end, motivations are incidental. I’m really just interested in
seeing how effective this is.
5 Comments
Thomas Ptacek | April 15th, 2008 | Filed Under: New Findings, This Old Vulnerability
The evidence is now overwhelming that Mark Dowd was, in fact, sent
back through time to kill the mother of the person who will grow up to
challenge SkyNet. Please direct your attention to Dowd’s 25-page bombshell
on a Flash bytecode attack.
Some context. Reliable Flash vulnerabilities are catastrophes. In
2008, we have lots of different browsers. We have different versions
of the OS, and we have Mac users. But we’ve only got one Flash vendor,
and everyone has Flash installed. Why do you care about Flash
exploits? Because in the field, any one of them wins a commanding
majority of browser installs for an attacker. It is the Cyberdyne
Systems Model 101 of clientsides.
So that’s pretty bad-ass. But that’s not why the fate of humanity
demands that we hunt down Dowd and dissolve him in molten
steel.
Look at the details of this attack. It’s a weaponized NULL pointer
attack that desynchronizes a bytecode verifier to slip malicious
ActionScript bytecode into the Flash runtime. If you’re not an exploit
writer, think of it this way: you know
that crazy version of Super Mario Brothers that Japan refused to ship to the US markets
because they thought the difficulty would upset and provoke us? This
is the exploit equivalent of that guy who played the perfect game of
it on YouTube.
Let’s break it down a bit:

Start with the vulnerability.
It’s an integer overflow, but not a simple one.
When the Flash runtime reads in scene data from a SWF file, there’s a
numeric field that, when bounds-checked, is interpreted as a signed
number, but when used is treated as unsigned. So there are values the
field can take that are treated as tiny and innocuous at
time-of-check, but actually evaluate as huge numbers at time-of-use.
A by-the-numbers integer overflow normally knocks the bounds checking
off a strncpy or memcpy call, turning code that carefully copies, say,
1k of memory into code that will copy 2 megs of data, splattering it
all over process memory. Not here. Instead, Flash uses the malicious
number as a count of bytes to allocate.
When you ask Flash to allocate several gigs of memory all at once, the
allocation fails, returning NULL. Attempt to use that NULL address and
you will crash the program. This happens all the time in real code.
Many crashes are traceable to NULL pointers. And, since nothing
(usually) lives at NULL, NULL pointer crashes are usually code for
“not exploitable”.
Not this time. Flash forgets to check that allocation failed, a
ludicrously common error. It then uses that pointer with an offset
controlled by the attacker. NULL isn’t valid. NULL plus 1024 isn’t
valud. But NULL + 0x8f71ba90 is, as is NULL + N for any N that
addresses valid memory.
To this address, controlled by attackers via wild offset, Flash writes
a value that is also controlled by the attacker. This is the write32
pattern: a vulnerability that gives the attacker the means to set any
one value in memory to a value of their choosing. Game over.

Except not quite.
The exploit doesn’t actually get to offset an arbitrary number of
bytes from 0. A complicated set of conditions constrains the address
it writes to and the value it gives it.
The the actual write occurs via a structure offset. Flash is hardcoded
to translate your offset into another number. Working offsets, as it
turns out, will be greater than 0x80000000, and will be evenly
divisible by 12 after 4 is added to them. Note: I thought I was
hardcore when I wrote shellcode with no lowercase letters for the IMAP
vulnerability in the ’90s.
That’s not all. The value that Flash will write to the wild pointer
isn’t totally controlled by the attacker either. It’s cast up from a
16 bit integer to a 32 bit integer, and has another variable
subtracted to it. This is the point in the report that I started
giggling uncontrollably, embarassing myself at the coffee shop.
The net result of this silliness is that it’s hard to do what
attackers normally do with a write32 vulnerability, which is to
clobber a function’s address with a pointer back to their buffer, so
that their shellcode is called when the clobbered function is
called. So Dowd’s exploit takes things in a different direction, and
manipulates the ActionScript bytecode state.
ActionScript bytecode state; yeah, about that.
ActionScript is Javascript that controls Flash animations. But the Javascript system
used by Flash is pretty advanced; for performance, it transforms
Javascript into bytecodes for a VM. For a bytecode VM, ActionScript is
pretty tight; its runtime stack is integrated with the CPU’s runtime
stack. The memory it uses to execute code is the same memory that the
Flash C-code runtime uses to manage its own state.
ActionScript is a register-based VM, meaning that its bytecode
instructions concern themselves chiefly with moving values in and out
of memory slots that simulate CPU registers. Those registers live in
the runtime stack and are accessed by indexing. Meaning, a malicious
Flash bytecode instruction can index its way to an arbitrary address
on the system stack. Game over.

Except not quite.
You can’t just inject malicious bytecodes.
Flash players have to execute bytecode sklorked directly off of web
pages, most of which are controlled by organized criminals. So Flash
doesn’t execute arbitrary bytecodes; they’re verified before
execution. The verifier ensures, among other things, that register
accesses from the bytecode stream reference valid register slots.
But. For performance, the Flash VM is broken into a two-pass system
with a verifier that validates bytecode (time-of-check) and an
executive that later evaluates it (time-of-use). And the interpretation
of bytecode differs at time-of-check and time-of-use. Here’s the
situation:
The verifier ignores undefined bytecodes.
The verifier keeps a table in memory that defines how long
any one bytecode instruction is.
The bytecode length table is a valid target of the NULL
pointer overwrite.
The executive has totally different machinery for interpeting
bytecode.
Clobber the right value in the length table, and you can make an
unused bytecode instruction that the verifier ignores seem much longer
than it is. The “extra” bytes slip past the verifier. But they don’t
slip past the executive, which has no idea that the unused bytecode
has trailing bytes. If those trailing bytes are themselves valid
bytecode, Flash will run them. Unverified. Giving them access to the
whole system stack. Game over.

Except not quite.
The Koopa shell on the second platform is a trap and if you touch it
you die.
Ok actually there’s no catch. Dowd’s exploit uses a NULL pointer
write32 to knock the locks off the bytecode interpreter in Flash, so
that his SWF file can run bytecode that will rewrite the system stack.
But, just to rub it in, or because this stuff just comes natural to
you when you are manufactured by a malicious cluster of supercomputers
inside SkyNet instead of nurtured by loving human parents, Dowd gives
himself additional constraints.
To wit: his exploit must (because he’s messing with us) corrupt the
Flash runtime, rewrite it to execute his trojan, and leave it running
steady as if nothing had happened. Meaning:
His modification to the verifier can’t break existing
instructions.
His bytecode has to swap values into the stack instead
of clobbering them directly.
Portions of his shellcode have to run as both Flash bytecode and
an X86 first-stage shellcode boot.

Two fun details.
First, even though IE and Firefox use different Flash builds, the
addressing inside them is compatible. The exploit works in both
places.
Second, Flash isn’t compiled with ASLR. So the attack works on
Vista.
Mass casualty. Go Flash!
101 Comments
Thomas Ptacek | September 25th, 2007 | Filed Under: Defenses, New Findings, Uncategorized
introduction
Alice and Bob want to arrange a tryst. Bob’s wife Eve is sniffing
their Instant Messenger traffic.
No problem! Alice and Bob will encrypt their messages with
AES-256-CBC. Eve won’t be able to decode the traffic before the
heat death of the universe.
One small problem: what AES key to use? Actually: not a small
problem. No matter what key Alice comes up with, she can’t send it to
Bob without exposing it. She can’t encrypt the key; chicken and egg.
number theory f.t.w.
There’s a solution to this problem. Alice and Bob will run the
Diffie-Hellman protocol (DH) to securely exchange a key.
Alice and Bob agree on a prime number p, and a smaller number g
with a special relationship with p ([1]). These are parameters to Diffie
Hellman. “23” and “7” are valid p and g parameters. So are “37”
and “5”. They aren’t secret. Think of them like a “version” of DH that
Alice and Bob agree to use.
For the sake of argument, Alice and Bob agree on “37, 5” DH.
Bust out your calculator. I’ll be Bob.
Generate a random number a, modulo 37 (divide your number by 37 and
a is the remainder).
I’ll do the same thing to generate a different b.
Now take your a and make A. Raise 5 to the a‘th power, modulo 37
(in Ruby, do “(5 ** a) % 37”. I’ll do the same with b to make B.
A is your public key. a is your private key. Send me A. I’ll
send you B. It’s 29.
Take 29 and raise it to the a‘th power mod 37 (I don’t know what a is;
it’s your private key, so I can’t tell you what you’ll get.) That’s
“(B ** a) % 37” in Ruby. I’ll do the same with B.
We just arrived at the same number. Was your private key 7? We came up
with 8. Was your private key 26? We came up with 27. 27 is our session
key.
Funny thing about our session key: you know it, and I know it, but
Eve can’t know it. Even though we did this computation out in the
open. This is the deep magic, yo.
quick aside:
Well OK, Eve totally knows what number we came up with, because we
used a ridiculously small p. Instead of 37, 5, try this:
FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF
Just use 2 as g. Remember now that your private key a is a random
number modulo this huge p. It will also be huge.
Raising a number to a power modulo another number is modular
exponentiation (modexp). A modexp is straightforward to compute.
The opposite of exponentiation is a logarithm. Taking a log mod
another number is a discrete logarithm. Discrete logs are extremely
hard to solve. With large enough numbers, “racing heat death of the
universe” hard; “every atom in the Solar System is a computer trying
to solve it, still unsolvable” hard.
So you have two closely related operations, exponentiation and
logarithm mod p, one of which is easy to compute and one of which is
hard. This is a cryptographic building block and the foundation of DH.
back to alice and bob
We got 26 for our session key. Let’s say we MD5 the text value of
“26”, to get “4e732ced3463d06de0ca9a15b6153677”. Tack a “0x” at the
front of that value, and we now have a 128 bit number we can use as an
AES key. Eve can’t know we came up with 26, and so can’t know what
the MD5 of the session key is, and so doesn’t know what our AES key
is.
Problem solved! Cue arbitrary foreshadowing device. We’ll come back
to this.
what adam bozanich found
Adam works for Mu Security. Mu is writing an IKE fuzzer. IKE is a
key exchange protocol for IPSec. IKE is probably one of the worst
protocols ever to come out of the IETF, and I’m not going to explain
it.
What you need to know is that IKE generates the keys that secure
dynamically-keyed IPSec tunnels (layer-3 VPNs), and that IKE uses DH
to do that.
Adam remembers a DH gotcha. When Alice and Bob run DH, they have to be
careful not to allow any of the parameters —- p, g, A, or B
—- be zero or one mod p.
Why’s that? Bust out your 37, 5 DH math again. Alice’s session key
computation is “(B ** a) % 37”. Bob sends B. If B is 1, the
session key is… wait for it… 1. If B is 0, it’s 0. No matter
what Alice’s private key is.
If Eve sees a public key that works out to 0 or 1 mod p, Eve
knows what the session key was; it’s zero or one. Remember that there
are infinitely many values that work out to 0 or 1 mod p. 0 is 0 mod
37. So is 37. So is 74. And so on. Bob could have sent any one of
those bad public key values.
Alice and Bob are supposed to check for this. Adam looked at a bunch
of IKE implementations. None of them did.
context
This is a well-known problem. It’s in Eric Rescorla’s DH RFC. It’s in
an ANSI standard. You can’t use p - 1 mod p either. You also have
to be careful with g; broken values will generate subgroups, not the
entire group. And real DH implementations have optimizations that can
be attacked mathematically if you’re not careful.
Just because it’s well known doesn’t mean people won’t make the
mistake. That’s why Nate and I pointed the problem out last year (almost
to the day!).
The general class of problems we’re talking about is parameter
validation. You attack them by looking at the messages a protocol
exchanges, and sending malicious bad values that will break the
computation.
Are you a security researcher? Go look for some of these bugs. They
rock. More in a sec.
but back to adam
So it’s interesting that IKE implementations don’t validate
parameters, but it’s not particularly meaningful.
IKE Bob can send IKE Alice a bad public key. This key will cause
Eve to know the session key Bob and Alice use. But why would Bob
do this? He’s negating his own security!
Eve can try to inject a bad public key into the session. But so
what? If Bob and Alice don’t agree on A and B, the public keys,
they can’t run DH. Maybe a different attacker, Mallory, can get
between Alice and Bob and proxy the messages. She’ll be a “man in the
middle”.
In this case, Mallory wins. No matter what parameters you use and what
bugs your code has, Mallory beats DH. This is a basic challenge with
DH. The solution involves more crypto.
DH is a useful building block, but protocols that use DH usually
depend on some other operation to ensure security. For instance, DH
SSL uses RSA certificates to beat Mallory. DH is useful to SSL; it
gives you perfect forward secrecy by not tying your SSL session key
to a fixed RSA key that can be compromised. But DH SSL depends on RSA
for security.
So it’s not a good sign that IKE implementations aren’t smart enough
to do parameter validation. But it doesn’t make much of a
difference. The “vulnerability” allows an IKE participant to elect an
insecure session.
accident? or… murder!
Adam wants to take this somewhere. So he writes a blog post suggesting
that the uniform weakness of IKE implementations could be evidence of
a conspiracy.
I don’t think he’s being entirely serious, but here’s his argument:
the NSA —- no wait, it’s 2007, let’s make it the RIAA —- demands the
ability to snoop on everyone’s IPSec sessions. They get all the IKE
vendors to ship backdoored IKE agents. On some secret signal, the IKE
agent will send public keys that work out to 0 mod p, and the RIAA
can break these sessions with the sniffers they’ve installed at every
exchange point on the Internet.
There’s a reason this is silly besides the fact that it involves
backdooring one of the least important security mechanisms on the
Internet: it’s a dumb attack.
Mallory knows p and g. So does Seth, the secops guy. Mallory can
watch for A and B values that are 0 mod p. So can Seth. Why
would the RIAA install a secret backdoor you could write an IDS
signature for?
There are much more subtle things you can do to backdoor DH. Start
with, IKE implementations can just be backdoored with a known private
key value, or a root backdoor private key and an algorithm for
generating variants of it. Move on from there.
This isn’t a conspiracy. This is just ignorance.
and I know that because…?
Because this vulnerability happens all over the place.
Take SRP for example. SRP is a derivative of DH. Alice is a client,
Bob is a server. Alice and Bob know Alice’s password. Alice generates
a public key that is related to the SHA-1 hash of the password. Alice
and Bob do a DH exchange to prove Alice knows the password, and if the
exchange works, Alice wins.
Mallory sends Bob a public key of 0 mod p. Mallory wins. She can log
in as Alice without knowing Alice’s password.
This vulnerability is well known. It’s in the RFC for SRP. But I’ve
tested SRP implementations written by smart security people, and
they’ve had this vulnerability. (Due credit: I got this trick from
Trevor Perrin, via Nate Lawson).
Compare the SRP vulnerability to the DH vulnerability. The SRP
parameter validation problem is really, really bad. It’s auth
bypass. The DH vulnerability is just a dumb way to backdoor an IKE
agent.
well played, adam
IKE is a mess of a protocol. Crypto parameter validation attacks are
totally underappreciated. Adam’s blog post is cool. It was smart of
him to check for this, and interesting that he found it.
and what have we learned?
Not much about IKE. It’s as secure as you thought it was before you
heard about Adam’s finding.
Hopefully a lot about crypto, though. Like I said, we wrote a post
last year talking about parameter validation tricks for DH, SRP,
Elliptic Curve, and RSA.
Forget about algorithmic attacks and advances in factorization and
quantum computers. Parameter validation attacks are a systems flaw;
systems depend on code, and code is riddled with bugs. All bugs are
vulnerabilities. Most… any? cryptosystems will be beaten by stupid
bugs like this.
Go look for them!
[1]: g is a primitive root modulo p. For values of x from 0 to
p - 1, raise g to x modulo p. If g is a primitive root
modulo p, you’ll end up with every number between 1 and p - 1, in
some order. For instance, the following Ruby snippet asks if 3 is
a primitive root mod 37.
lst = [] ; 0.upto(36) {|d| lst << ((3 ** d) % 37)} ; lst.sort
elicits the following output:
[1, 1, 1, 3, 3, 4, 4, 7, 7, 9, 9, 10, 10, 11, 11,
12, 12, 16, 16, 21, 21, 25, 25, 26, 26, 27, 27, 28,
28, 30, 30, 33, 33, 34, 34, 36, 36]
2’s missing. So’s 5 and 6, etc. 3 is not a primitive root mod 37. Now
try 5:
lst = [] ; 0.upto(36) {|d| lst << ((3 ** d) % 37)} ; lst.sort
[1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36]
All the numbers between 1 and 36 are there. 5 is primitive root mod 37.
Why is this important? Because if you’re working with a 1024 bit prime, you want session key values to possibly be any one of those 1024 bit values. Another word for “primitive root” is generator. Generators generate the entire group of values mod p. Bad values of g generate subgroups, with fewer than 1024 bits of possible values. The worst g values generate only two possible values!
7 Comments
Thomas Ptacek | August 22nd, 2007 | Filed Under: Disclosure, New Findings
RSnake discovers that Google gadgets can be coerced into
rendering arbitrary Javascript tags, and reports it to Google.
Google responds, in effect, “that’s one of the reasons why they
live under gmodules.com”, continuing, “If you do find a way of
executing this code from the context of a google.com domain,
though, please let us know.”
RSnake decries a “slap in the face”, saying “Google needs to figure
out what XSS is used for”. Attackers can set up phishing
sites on “Google-branded domains”.
Um, RSnake.
Phishers can create “Google branding” on any site they
want. That “Google branding” is just a GIF. Pretty sure
Javascript anywhere can put it on the screen.
That same “vulnerability” appears to be present on Blogspot.
Presumably, on Typepad, Livejournal, and Wordpress as well.
Last time I saw a Bank of America phish, the logo wasn’t
drawn in Windows Paint. I didn’t blame Bank of America.
Likewise, I’m not sure it’s hard for phishers to find or
create infected domain names that start with the letter ‘g’.
What, exactly, do you want them to do? I like your stuff and all that,
and if it’ll make you happy, I’ll bribe Dave to give you a Pwnie for
“best Google hack” over this —- but, am I wrong about this? Or are you?
19 Comments
Thomas Ptacek | July 12th, 2007 | Filed Under: New Findings, Uncategorized
Via Slashdot:
You’re a bad guy sharing a Linux server with a bunch of good
people. All of you are running processes and those processes share
access to the CPU by working in 10-100 millisecond time slices. This
is called multitasking.
You don’t want to share because you’re bad. So unlike the good people,
your processes:
Figure out how long a timeslice is in cycles
Sync themselves to the start of a clock tick with a
scheduling no-op nanosleep()
Execute for fewer instructions than is allocated to
a process time slice.
Yield back to the scheduler with another nanosleep().
The result, on many OSs, is that the scheduler basically doesn’t
“notice” you ran. You get an unfair share of scheduler resources, or
even monopolize the CPU.
Yawn.
A question: anyone researching attacks against hypervisor scheduling
algorithms? Nobody shares an OS kernel with other people anymore, but
in a few years everyone will share iron in side-by-side VMs. I mean,
apart from things like Linux KVM virtualization (which is just
processes, so is presumably affected somehow).
No Comments
Thomas Ptacek | July 12th, 2007 | Filed Under: New Findings, Uncategorized
[Update 7/12]
This post touched a nerve on Reddit. C++ programmers, unsurprisingly, have some issues with this post. Go read the Reddit comments; they’re excellent. And then vote my post up!
1.
Almost 10 years ago, during the dot-com bubble, I did what many
security pros before and after me did and “gave up on security” to “go
do something meaningful” [∗]. I was at Network Associates (after they
bought Secure Networks), and David Meltzer, my alter-ego at ISS,
recruited me into a startup along with Danny Dulai and Tim Newsham. We
wanted to build the chat system of the future, and we ended up with
application-layer multicast streaming media. In 1999. We were a bit
ahead of our time [∗∗].
This is good to know because it will help you avoid ever starting
a discussion with me about reliable multicast protocols (down with
forward error correction!) or source-specific multicast routing (down
with source-specific multicast routing!). But why I bring it up is, we
wrote it in C++. We wrote a lot of C++. A lot. We used ACE. Used ACE
before? You know how much C++ we were swimming in. A lot of
C++. Template-y, Boost-y, Alexandrescu-understandingy C++.
2.
Now this is a security blog, and so I’m supposed to be using this time
to make a point about security, and that point is this: the notion
that C++ is a more secure language than C is a myth. C++ gives you a
dynamically-resizeable string class, which makes it less likely that
you are going to write the splitvt overflow. But it also gives you a
dozen new features which, if you use them wrong, segfault your
program.
3.
Take exceptions. C++ has built-in support for exceptions; when
something horrible happens, you “throw” a variable that any stack
frame up the call chain can “catch”. This is better than returning a
cryptic error code, because you can’t forget to check it.
But. When you throw an exception, you effectively “abort” your current
function, and all the functions in the call chain up to the point
where the exception was caught. If any of these functions aren’t
written to anticipate getting preemptively aborted, and hold on to a
pointer or a chunk of memory, you’ve got a memory lifecycle bug.
This problem is well known to the C++ community. Herb Sutter wrote a
famous article about it, which invented the notion of “exception-safe”
C++ programming. Joel Spolsky wrote a JoelOnSoftware about it. There’s a
debate about whether C++ exceptions are evil.
But it’s not well known problem to the security community. A year or
so ago, Mark Dowd found yet another Sendmail vulnerability. Sendmail
is written in C, not C++, but it uses Unix signals and “longjmp” to
emulate C++ exceptions, and (it’s Sendmail, after all) isn’t written
exception-safe. You can trigger a timeout exception, and Sendmail will
retain an invalid pointer into the stack that it would have cleared
out if the exception hadn’t occurred. That pointer can be used to
scribble over stack frames.
Any time you have a language feature, and you have to think about
writing code to be “that-language-feature-safe”, you have a security
problem. Because that feature is creating bug classes. Bug classes are
bad. Splitvt? That’s a bug. Stack overflows? Bug class. Stack
overflows cost the industry over $700MM. Exception-safety problems?
Bug class. One that C++ introduces.
4.
Want another example? Destructors. Mark Dowd and John McDonald wrote a
blog post about it a few months back. Do you audit code at your job?
It’s one of the top #10 most valuable blog posts of the year. Long
story short? If you call “delete[]” instead of “delete” —- which is
an exceedingly common C++ error —- you’ve introduced a potential
vulnerability. Like integer overflows, a bug class.
5.
Here’s another example: the STL. STL (or, more properly, the Standard
C++ Library) is the collection of container classes C++ provides. In
C, if you want a hash table, you have to implement it yourself. In C++
—- bad example. But if you want a red-black tree with the same API as
a hash table, it’s provided for you. Also linked lists, resizeable
arrays, and something called a dequeue (prounced “woon”). The STL is
one of the great features of C++.
It’s also a reliability disaster. Here’s why: STL containers try to
hide pointers from you. Instead of pointers, you get “iterators”,
which are objects with a variety of interesting methods and generic
functions that operate on them and all sorts of other fancy gunk and
at the end of the day it’s all just 1500 lines of C++ template code
wrapping: a pointer.
STL tries to avoid the most common pointer bugs, like walking off the
end of an array into bad memory. But some bugs can’t be avoided. So
for instance: if you modify an STL map (which is a red-black tree) [∗∗∗] vector or dequeue,
you invalidate all your outstanding iterators. Modifying a
red-black
tree container potentially repositions the nodes they pointed to, and all that
fancy OOP gunk aside, iterators are just pointers, not magic. If you
hold references to those invalid iterators, they now point to invalid
addresses.
This is an absurdly common problem. I’m an OK developer, if I do say
so myself, but Danny Dulai, Kneel Fachan, and Tim Newsham are just
fucking insanely talented developers and they ran into these
problems, just like me.
And again, this problem is well known in C++-world (there’s a whole
very excellent book about it). But it’s not well known in the security community.
And when you screw it up, it’s potentially exploitable.
6.
C++ gives you a resizeable string, so you won’t write splitvt. But in
2007, code vulnerabilities don’t look like splitvt anymore,
ever. We’ve moved on, through off-by-one errors into integer overflows
and now uninitialized variables. On balance, the bug classes
C++ introduces are way scarier than the ones it takes off the table.
So, to kick off our series of posts about which Black Hat talks you
should be going to this year, I’m going to recommend this one. Mark
Dowd and John McDonald, on stage, talking about the ways C++ screws
software security that you hadn’t thought of before. “Recommend” is an
understatement. If you get paid to find vulnerabilities in code, this
is the most valuable talk at the conference this year.
See you there!
[∗] For the most recent example of this phenomenon, see Dug Song.
[∗∗] This is marketing-speak for “wrong”; you can say the same thing
for a batter’s swing when he takes a strike.
[∗∗∗] Deleting map nodes invalidates some iterators in a map, but adding nodes doesn’t. Breathing on a dequeue invalidates iterators.
31 Comments
Thomas Ptacek | June 27th, 2007 | Filed Under: Defenses, New Findings, Uncategorized
Nate Lawson, spilling the beans on our some of our Black Hat plans:
“The crux of the matter is that a perfect emulator of any
sufficiently complex system would have to be a bug-free program, and
we don’t know how to write those yet,” he argued. “The important
thing to consider when writing a rootkit is what layer to implement
it at. Joanna chose “entire x86 PC”, which we argue is too big a
cross-section.”
Joanna, we respectfully request terms under which you’d agree to an
“undetectable rootkit detection challenge”. We’ll concede almost
anything reasonable; we want the same access to the
(possibly-)infected machine than any antivirus software would get.
The backstory:
Dino Dai Zovi, under Matasano colors,
presented a hypervisor rootkit (“Vitriol”) for Intel’s VT-X extensions at Black Hat last year,
at the same time as Joanna presented BluePill for AMD’d SVM.
We concede: Joanna’s rootkit is coolor than ours. I particularly
liked using the debug registers to grab network traffic out of
the drivers. We stopped weaponizing Vitriol.
Peter Ferrie, the Symantec branch of our Black Hat team, releases
a kick-ass paper on hypervisor detection. Peter’s focus is
on fingerprinting software hypervisors (like VMWare), but he also
comes up with a clever way to detect hardware virtualization.
Nate Lawson, Dino, and I are, simultaneously, working on hardware
rootkit detection techniques.
Nate, Peter, Dino, and I join up to defend our thesis at Black
Hat: if you surreptitiously “hyperjack” an OS, enabling hardware
virtualization (or replacing or infecting an existing hypervisor),
you introduce so many subtle changes in system behavior —- timing
and otherwise —- that you’re bound to be detectable.
And so the stage is set for our Black Hat talk.
For the record: I’m the least scary member of this particular team,
but have likely written the most code (by LOC) behind the
talk. Obviously, Dino’s Vitriol work is what made it possible for us
to figure this stuff out, and Joanna’s BluePill work —- which we
haven’t seen —- is what makes it interesting.
I’ll have more to say in the coming weeks.
9 Comments
Thomas Ptacek | June 27th, 2007 | Filed Under: New Findings, Uncategorized
Our commenters will be more useful than I will on this post, but:
Theo de Raadt on Intel CORE 2:
These processors are buggy as hell, and some of these bugs don't just
cause development/debugging problems, but will *ASSUREDLY* be
exploitable from userland code.
Errata he calls out specifically:
AI65
When the temperature reaches an invalid temperature the CPU does not
generate a Thermal interrupt even if a programmed threshold is
crossed.
I don’t see how this is a security concern; maybe he meant AI56,
which gives unpredictable behavior if you change the attributes of a
PTE without fixing up the TLB; AI64 involves system management mode
and AI67 involves VTX.
AI79
During a series of REP (repeat) store instructions a store may try to
dispatch to memory prior to the actual completion of the instruction.
This behavior depends on the execution order of the instructions, the
timing of a speculative jump and the timing of an uncacheable memory
store. […] When this erratum occurs, the processor may live lock
and/or result in a system hang.
Unless the behavior depends on system memory inaccessible to
userland, this could imply userland crasher exploit.
AI43
When a logical processor writes to a non-dirty page, and another logical-
processor either writes to the same non-dirty page or explicitly sets the dirty
bit in the corresponding page table entry, complex interaction with internal
processor activity may cause unpredictable system behavior […] and hang.
Two userland processes on two different cores can race each other and
hang the system?
AI39
When request for data from Core 1 results in a L1 cache miss, the request is
sent to the L2 cache. If this request hits a modified line in the L1 data cache
of Core 2, certain internal conditions may cause incorrect data to be returned
to the Core 1.
Where the word “incorrect data” is errata code for “Zuul’s return as
the Sta-Puft Marshmellow Man” —- two cores race each other, and a
process gets the wrong cache line.
AI90
If code segment limit is set close to the end of a code page, then due
to this erratum the memory page Access bit (A bit) may be set for the
subsequent page prior to general protection fault on code segment
limit. […] a non-accessed page which is present in memory and
follows a page that contains the code segment limit may be tagged as
accessed.
Theo says this is exploitable on operating systems other than OBSD;
the A bit signals the VM system that a page has been accessed by the hardware.
AI99
Code #PF (Page Fault exception) is normally handled in lower priority order
relative to both code #DB (Debug Exception) and code Segment Limit
Violation #GP (General Protection Fault). Due to this erratum, code #PF may
be handled incorrectly, if all of the following conditions are met:
A PDE (Page Directory Entry) is modified without invalidating the
corresponding TLB (Translation Look-aside Buffer) entry
Code execution transitions to a different code page such that
both:
One of the following simultaneous exception conditions is present following the
code transition:
Software may observe either incorrect processing of code #PF before code
Segment Limit Violation #GP or processing of code #PF in lieu of code #DB.
We’ll have more to say about chip errata this month.
2 Comments
Thomas Ptacek | May 1st, 2007 | Filed Under: Apple, Disclosure, New Findings, Uncategorized
As Dave noted, Apple has released a patch for Dino’s QuickTime
finding. 3Com followed up with their advisory. Direct your attention
to the nut graf:
The flaw exists within the QuickTime Java extensions (QTJava.dll),
specifically the routine toQTPointer() exposed through
quicktime.util.QTHandleRef. A lack of sanity checking on the
parameters passed to this routine, through the Java Virtual Machine
(JVM), allows an attacker to write arbitrary values to memory.
What this is saying:
If you have the QuickTime for Java extensions installed
(in other words, if you have QuickTime installed),
then a Java applet will be allowed to construct and play
with QuickTime objects, which are backed with unprotected C
code,
and specifically, some of those objects wrap pointers
to memory tracked by a dynamic C library,
and unfortunately those objects are not careful enough
with the values passed to them by Java code,
so Java applets can overwrite arbitrary process memory
directly,
which they should never be able to do, because keeping
Java applet code from touching memory directly is the whole
point of the applet sandbox.
The vulnerability appears to be an integer overflow. Translated to
minimal Java code (say, the init method of an applet), it reads:
// Initialize QT
QTSession.open();
// Get a handle to anything
byte b[] = new byte[1 /*arbitrary*/];
QTHandle h = new QTHandle(b);
// Turn the handle into a pointer object. The
// large negative value throws off bounds checking.
QTPointerRef p = h.toQTPointer(-2000000000 /*off*/, 10 /*size*/);
// Write to it.
p.copyFromArray(0 /*offset*/, b /*source*/, 0, 1 /*length*/);
In applet form, this reliably crashes my browsers. It is both
deliberately and organically far from being useful to an
attacker. Note that without comments, it’s 5 lines of code.
Get this one patched quickly! From the ZDI advisory and the QTJava documentation it looks like it takes very little time to figure this one out.
[Update: 11:00PM EST]
Read carefully and note that ZDI’s advisory confirms QuickTime for Vista is vulnerable.
26 Comments
Thomas Ptacek | April 24th, 2007 | Filed Under: Apple, Defenses, Disclosure, Industry Punditry, New Findings
This just in: anonymous sources at 3Com confirm Dino’s QuickTime vulnerability is exploitable in IE7 and IE6 on Windows XP.
Watch this space for details (Is XPSP2+DEP reliably exploitable? You can’t run IE7 on XPSP1 —- so, probably! Vista?) as they’re made available to us.
I think we can now safely conclude: this is a hell of a finding. Way to go, Dino!
Irony Alert
Consider the possibility that the one platform this vulnerability won’t work against is Windows Vista.
[Update: 4/25]
As usual, the comments on this post are much more valuable than anything I’ve written. Rosyna Keller and Skywing are discussing the protection mechanisms in IE6/IE7 (anyone know what the equivalent protections are in Safari? Oh, wait…).
More importantly, our source at 3Com has re-confirmed that IE6 and IE7 are vulnerable to this attack. More details about the vulnerability as they become available.
[Update: 4/27]
I’m simply deleting comments that say things like “XXX is not vulnerable” or “YYY is vulnerable” without evidence.
32 Comments