Archive for the ‘This Old Vulnerability’ Category
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!
98 Comments
Dave G. | July 30th, 2007 | Filed Under: This Old Vulnerability
Welcome to the pre-blackhat edition of This Old Vulnerability. iDefense recently put out an advisory on AIX’s ftp client. Let’s start out with a joke:
Knock Knock!
Who’s There?
AIX’s Team.
AIX’s Team Who?
AIX’s Team, who, besides you, ships ftp clients setuid root in 2007?
Yeah. I don’t get it either. Now you might think that is the most humorous thing I can say about AIX’s setuid root ftp client. Sadly, you are mistaken. This ftp client has had a history of security vulnerabilities. Let’s talk about the most recent iDefense one and work our way back.
This setuid-root ftp client has a buffer overflow in it. Not just a buffer overflow, but a stack-based buffer overflow (I could swear it’s 2007). Not just a stack-based buffer overflow, but the most simple kind, an unbounded read from user input. (I don’t remember 2006 very well, but all of my computers say 2007) Even more entertaining, it is due to calls to gets(). (Is this the Morris worm? Am I trapped inside of 1987?)
To understand this further, I caught up with one of the world’s foremost authority on gets():
Q: gcc What do you think of the gets() function?
A: gcc: What: No such file or directory
gcc: do: No such file or directory
gcc: you: No such file or directory
gcc: think: No such file or directory
gcc: of: No such file or directory
gcc: the: No such file or directory
gcc: gets(): No such file or directory
gcc: function?: No such file or directory
gcc: no input files
Q: Oh, sorry, my bad. I will submit my question in the form of C code.
gcc -o gets-question gets-question.c
A:
/tmp/ccPW3krf.o: In function ‘main’:
/tmp/ccPW3krf.o(.text+0x24): the ‘gets’ function is dangerous and should not be used.
Q: Thank you for your time.
So, to recap, in the year 2007, there is a commercial operating system shipping a setuid-root ftp client with calls to gets() in it.
Now, this story could end here. Old forgotten code that no one has looked at in awhile. However, I distinctly remembered that there has been a history of vulnerabilities in this superfluously setuid root code. Almost as good as the sendmail debug vulnerabilities, the archive footage for this vulnerability shows:
AIX ftp tftp and utftp Core Dump Vulnerability
Some versions of ftpd, tftpd, and utftpd under AIX use the gets() system call to gather information from standard input (STDIN). The gets() system call has no means to denote size of the string it is handling and allows for an infinite amount of data to be passed into it. The problem lies in that the code in ftpd tftpd and utftpd which takes data from the gets() call places it in a fixed buffer. This buffer can be overflown resulting in the applications dumping core. Because these programs are run as root, the core images may contain critical root owned pieces of memory, such as user names and passwords.
The description is totally confusing at first. The title says it’s the clients that have the vulnerabilties, but the description says it’s the servers. Which are we to believe? I believe it to be the clients. I believe this for two reasons.
The title for the vulnerability can be found in other documents on the Internet.
There is no evidence that AIX shipped with a utftpd. But you can find man pages for a utftp with is a version of tftp for use in pipes.
I wonder if these are the same gets() calls from the iDefense advisory. I really wonder how they fixed the original vulnerabilities (rlimits on coredumps?). I really really wonder why this all has to be setuid…
Here are some other vulnerabilities that have impacted their ftp client in the past:
IX70885 SECURITY: FTP CLIENT INTERPRETS SERVER PROVIDED FILENAMES. The ftp client can be tricked into running arbitrary commands supplied by the remote server. When the remote file begins with a pipe symbol, the ftp client will process the contents of the remote file as a shell script.
IX85556 SECURITY: BUFFER OVERFLOW IN FTP CLIENT. When parsing a 227 message, the ftp client may generate a segmentation violation and core dump. (and by segmentation violation and dump core, we mean run attacker supplied machine code as root).
IY13781 SECURITY: FORMAT STRING VULNERABILITY IN FTP CLIENT. The ftp client shipped with AIX version 4.3.X contains a format string buffer overflow in the quote command. Since the ftp client is setuid root, this allows a local attacker to gain root privileges.
ftp> !/bin/sh (*)
(*) I really remember this being a vulnerability, but can’t find confirmation. It is possible that I have implicated ftp in tprof’s crime.
7 Comments
Dave G. | May 18th, 2007 | Filed Under: This Old Vulnerability
Today on This Old Vulnerability, we will take a quick tour through a classic metacharacter/delimiter injection attack. Our petri dish will be Sendmail 8.6.9 (and 8.6.10). The vulnerability was caused when sendmail would take input from a remote identd (the username) and blindly write it into a sendmail queue file. Normally, the output from identd would look something like:
srvrport , clientport : USERID : UNIX :username
Sendmail was just trying to grab the username. However, since no input validation was performed, an attacker could write their own identd that would return a response like:
25,25 : USERID : UNIX : Croot\r\n
Mprog, P=/bin/sh, F=lsDFMeu, A=sh -c $u\r\n
Mlocal, P=/bin/sh, F=lsDFMeu, A=sh -c $u\r\n
R<"|/bin/echo toor::0:1:toor:/:/bin/csh >> /etc/passwd”>\r\n
R<"|/usr/bin/chmod 4755 /usr/bin/time\r\n
As you can probably guess, everything past the “UNIX : ” part will get deposited into a sendmail queue file. Furthermore, you can probably guess that a sendmail queue file with that cruft in there will eventually cause sendmail to add a user called ‘toor’ with root privileges and no password, and make /usr/bin/time setuid root. A setuid time is bad because:
$ /usr/bin/time /bin/sh
will execute /bin/sh as root (This was a long time ago, and for its day considered clever, not unlike myself).
I think we should consult the sendmail release notes and see what they have to say about this vulnerability:
SECURITY: Diagnose bogus values to some command line flags that
could allow trash to get into headers and qf files.
Validate the name of the user returned by the IDENT protocol.
Some systems that really dislike IDENT send intentionally
bogus information. Problem pointed out by Michael Bushnell
of the Free Software Foundation. Has some security
implications.
The authors of sendmail had a very simple fix for this. Look for occurences of newline (’\n’) characters and change them to the space character. Alas, it appears that through the use of queue file continuation lines, an attacker could add a bunch of tabs and trigger the same vulnerability (*).
(*) I will admit to not being 100% sure of this, but it my best guess based on 2 seconds of reviewing an exploit, the diff and google, as you can tell from the lack of posting, time to read sendmail diffs is a luxury I don’t have. It is entirely possible that the root cause is something else entirely, that the exploit never worked or that it was fixed later than 8.6.11. There was another patch for this vulnerability in 8.6.13.
No Comments
Dave G. | November 15th, 2006 | Filed Under: This Old Vulnerability
As we sit here, somewhere around the cusp of integer overflows (some will say we are past the peak) and signed/unsigned comparison bugs, I wanted to reflect back on the earliest one that I can remember. First, lets set the stage.
The year was 1994, which means it was likely that I was wearing flannel, Jeremy was listening to New York Hardcore (not unlike 2006), Dino wasn’t allowed to stay up past 11PM (not unlike 2006), and Tom was wearing all black (also not unlike 2006). March was actually a crazy month for vulnerability research. 8LGM posted their first 4 security advisories (predated back as far as 1991). And sendmail bugs would come out somewhere between weekly and monthly.
Let’s take a look at the first post:
I mailed to both CERT and the Sun security email addresses over a month back.
Neither replied until I mailed again explicitely asking whether or not they’d
even received my mail. Having heard nothing for a month now I’ve decided to
mail here.
If people are wondering why the research community has had rocky relationships with vendors and CERT, this is one example of many from that time period that got us all off on the wrong foot.
There is a bug in many versions of sendmail to do with the -d command line
option. This allows setting of arbitrary elements of the debug array. I first
heard of the bug whilst examining the IDA sendmail source code 2-3 years back.
Wow, so this bug was known back in 1991. I was listening to heavy metal bands like Metallica, Iron Maiden, and Suicidal Tendencies (not unlike 2006). Sendmail+IDA is long gone, and was slightly easier to configure than sendmail.
To test if your sendmail has it, try using -d with a mumber greater than max
signed int, and less than max unsigned int, that preferably is substantially
far enough from either to be well outside normal address space ranges when
used as an array index.
Eg:
$ sendmail -d3294967296
Now this was in a time before buffer overflows and other memory trespasses were the technique du jour. Back then, normal exploitation techniques involved:
- IFS=/
- PATH=.:$PATH
- {|;} /bin/sh
- ln -s /tmp/something /.rhosts
Let’s see get some more detail and see how they tried to exploit it:
The problem is that with -d arguments between max signed int and max unsigned
int pass the valid-range (0-99 inclusive) check. The result is that it is
possible to write to areas of memory prior to the debug array. With a bit of
trickery the pathname of the sendmail config can be deduced as an offset from
the debug array. Hence the leading slash can then be changed to a ‘.’ to
produce a relative pathname.
Not bad… with a one byte memory corruption, root is obtained. Alas, the exploit doesnt actually do the one byte change of a ‘/’ to a ‘.’, but instead writes out a whole new path, one -d at a time.
When this bug came out, I remember talking to Tim Newsham about it, and my head pretty much exploded. I had even logged the conversation, but alas, I think that disk is long gone.
Of course, we probably wouldn’t try something like that post memory trespass renaissance. I wonder what would happen if that bug had come out in a post buffer overflow world. It’s a shame that people learn from their mistakes.
[FAST FORWARD TO 2001]
I am still listening to heavy metal, jeremy is still listening to ny hardcore, tom still wears black, Dino is still in bed by 11PM and sendmail is still vulnerable to the exact same vulnerability.
This one vulnerability (implemented twice) was known about and exposed in sendmail for at least 4 years.
This one uses a more time appropriate exploitation technique, kickin’ it with the GOT.
|
The Bugtraq Patch (1994) | The FreeBSD patch (2001) |
tTflag(s)
register char *s;
{
- int first, last;
- register int i;
+ unsigned int first, last;
+ register unsigned int i;
if (*s == '\0')
|
tTflag(s)
register char *s;
{
- int first, last;
+ unsigned int first, last;
register unsigned int i;
if (*s == '\0')
|
Of course, 8.10.2 to 8.11.0 was a big version jump for sendmail, they probably re-implemented a lot of functionality in the tracing subsystem, right?
$ diff sendmail-8.10.2/sendmail/trace.c sendmail-8.11.0/sendmail/trace.c
15c15
< static char id[] = "@(#)$Id: trace.c,v 8.20 1999/08/02 21:44:36 ca Exp $";
---
> static char id[] = "@(#)$Id: trace.c,v 8.20.22.1 2000/05/25 18:56:18 gshapiro Exp $";
66c66
< unsigned int first, last;
---
> int first, last;
Why would someone make that change? It is highly unlikely it was a source control problem, because:
- Who would accidentally be using the tTflags() function from 1994 in 2001?
- Even if they did, the variable underneath it was left as unsigned in 8.11.x
Can anyone think of a reason as to why someone would make this change? Because I am coming up with a blank other than gross incompetence or an intentional backdoor created by either a sendmail developer or someone who compromised the sendmail source code. Anyone from sendmail know why this change took place?
Am I being paranoid, or are they really out to get us? What other ways could this have happened?
Memorable Quotes
A quote from: Peter Wemm (petergecko.dialix.oz.au) on Mon, 28 Mar 1994 :
Oh. Joy! However, with the intense security that sendmail is getting
at the moment, I can’t imagine that there’s too many undiscovered
holes left now..
From Sendmail 8.6.7 dist:
SECURITY: it was possible to get root access by using wierd values to the -d flag. Thanks to Alain Durand of INRIA for forwarding me the notice from the bugtraq list.
From Perry Metzger:
So, does anyone know anything about this new Sendmail bug other than that it exists?
From “Evil Pete” Shipley
has anyone acutaly obtained root with the -d option?
3 Comments
Thomas Ptacek | May 17th, 2006 | Filed Under: This Old Vulnerability
It’s a dark and stormy night. Theo relaxes contentedly in the
basement. Idly polishes a cherished stack of Sun IPX’s. Pauses now
and again to berate his developers on ICB.
He has reason to be smug. His team has just finished an audit of the
OpenBSD userland code, establishing for a glorious ten days a factual
basis for OpenBSD’s security boasts and a role for Theo as a lanky,
cave-dwelling Sun King of open source security. In some cases, his
auditors didn’t even use ‘grep’ to find their stack overflows,
meticulously scanning loops by hand to root out vulnerabilities. Such
is OpenBSD’s greatness during this eternally memorable age.
Devil’s work. Idle hands. Theo picks up a project. OpenBSD doesn’t have
kernel threads. Theo doesn’t like threads. Plan9 has an alternative:
true lightweight processes. You fork them like normal processes, but they
can share memory and file descriptors. You create them with the rfork
system call.
Time passes. A year almost to the day. Champion competitive cup-stacker
Danny Dulai (credo: “People with 1 tongue have no idea what they are missing”)
is poking around at OpenBSD. “Isn’t this a security problem, Theo? Theo?
Wake up, Theo. Here, have some free SCSI cards.” Free hardware… Theo
rouses from a malarial stupor.
Panic. Commotion. An advisory. It is a problem: rfork conflicts with
the Unix security model. It gives parent processes control over SUID
child processes. A user runs “passwd”, which assumes superuser creds
to edit the password database. But passwd is working with the user’s
descriptor table, not its own, and as it opens sensitive files, it’s
handing them directly to the user. The kernel checks access at open(),
not on “read()” or “write()”.
The patch is easy (don’t honor SUID when exec is called on a process
that shares a descriptor table). So easy that Linux had it from the start.
A strange anomaly. The Sun King has introduced a vulnerability into OpenBSD.
It will never happen again. Rfork goes on to be such an important part of
the BSD API that calamity ensues when the most popular BSD fails to officially
include it.
Years later, FreeBSD manages to snatch defeat from the jaws of not
working with Theo. Georgi Guninski, of the one legitimate qmail finding,
notices that FreeBSD has added functionality to rfork;
with RFSIGSHARE, FreeBSD rfork also shares signal handlers with the
child process. User aims SIGINT handler into the
environment. Populates the environment with shellcode. Runs “passwd”,
RFSIGSHARE. Delivers SIGINT. “passwd”, running as root, with the
inherited poisoned SIGINT handler, diverts control to the user’s code.
Somewhere in the celestial clouds, an angel chokes, clutches its
throat, breathes its last, and expires.
2 Comments
Dave G. | April 13th, 2006 | Filed Under: This Old Vulnerability
I am quite positive that when this vulnerability reached Sun, someone’s
head exploded. Unravelling from the core of the vulnerability, we had
a botched fix to a seemingly local automountd vulnerability.
The problem?
The ability to execute arbitrary commands via a supposed RPC call that trickled user supplied data to a popen().
Why was it local?
Because automountd doesn’t listen on any TCP or UDP. But it could accept packets via the Transport Layer Interface(TLI) API.
The fix?
Replace popen() with execve().
The problem with the fix?
The RPC call in question didn’t just let you set command line arguments, but also the command itself. OOPS!
So another 1999 Solaris local… how does this get remote?
Glad you asked… Enter statd! Turns out that via SM_MON and SM_NOTIFY RPC requests, you can forward arbitrary RPC requests to arbitrary RPC services. Not only that, it was capable of using TLI as a transport mechanism.
Wow! Let me get this straight… I send a couple of packets to statd (which was listening on multiple port and protocols remotely) and I can execute a command of my choosing on a remote Solaris 2.5 -> 2.7 machine?
Almost. It turns out that on Solaris 2.6 and 2.7, you also had to slide
past a call to SMHASH(). Let’s look at this amazingly complete explanation of the bounce vulnerability, we see:
Because of the way SMHASH works and the way RPC arguments are encoded, our command is what SMHASH attempts to lookup in its address tables once rpc.statd receives our packet. If SMHASH cannot detect if our command is a valid address, it will not forward the packet.
How do you get around that?
You needed to be able to control/spoof DNS, so that your DNS entry matched the command you were trying to execute. How’s that for badass?
The exploit (minus the DNS stuff), is located here.
In short, combining a botched patch, with TCP/UDP -> TLI protocol traversal and maybe some DNS spoofing, and you are root. It’s just that simple!
5 Comments
Dave G. | April 3rd, 2006 | Filed Under: This Old Vulnerability
They bang the gong for this one! I am going to tell the story of this Solaris 2.4 kernel vulnerability in reverse order.
First lets look at the comment from the exploit:
/*
If a tty port that is writeable by the user and owned by root is
opened and the I_PUSH “ms” ioctl call made followed by an lseek
the effective uid of the user is changed to root.
*/
I think I just dumped core.
Lets see what the folks on bugtraq had to say. Consolidating Casper Dik and jsz we get:
The problem is that the code uses and changes the user’s cred
structure, instead of allocating a new one (which is what happens
in Solaris 2.2 and earlier).
…
But seriously, as someone has already said, the bug is in one of the routines
of the driver in the kernel, which passes a pointer to u-cred structure
and the routine actually modifies the uid and gid (euid & egid as well) to
zero.
Finally, lets look at the three line kernel exploit:
fd = open("/dev/ttyb", O_RDWR);
ioctl(fd, I_PUSH, "ms");
lseek(fd, 0, 1);
2 Comments
Matasano Team | March 23rd, 2006 | Filed Under: This Old Vulnerability
Vulnerability researchers have been increasingly focused on kernel level vulnerabilities. While a lot of progress has been made in the past couple of years, I thought it would be cool to dig up some really old kernel vulnerabilities. Oh look, here’s one now!
On this installment of This Old Vulnerability, we are going to examine
a kernel vulnerability that affected SunOS 4.1 and 4.1.1 (as opposed to a new vulnerability in SunOS 4.1.x). Let’s see what CERT had to say about the Integer Division vulnerability we are going to examine today.
I. Description
A security vulnerability exists in the integer
division on the SPARC architecture that can be
used to gain root privileges.
II. Impact
Any user logged into the system can gain root
access.
Helpful as ever!
Let’s ask Spaf via the Core mailing list. Spaf, I having a difficult time comprehending this CERT advisory, can you help?
Regarding the integer division problem.
It’s not that difficult to comprehend. Just set up a divide
instruction, and set it so the remainder is to be stored in any
arbitrary address you want (you have to do this in assembler, although
the % operator in C may let you do this…I dunno).
Then divide appropriately chosen numbers. The instruction traps, the
divide is emulated, the results are stored *in privileged mode* and
control is passed back to the user. No problems! However, the
address specified for the remainder may not be in the user’s memory
space.
Appropriate choice of values to be stored and locations to be stored
into result in all sorts of fun results.
Thanks Spaf!
Finally, lets track this back to the source:
printf("enter address in hexn");
gets(buf);
sscanf(buf, "%x", &addr);
addr -= 32;
pp = (unsigned long *) addr;
printf("address is 0x%0.8xn", addr);
if (fork() == 0) {
asm(" sethi %hi(_addr), %i4");
asm(" ld [%i4+%lo(_addr)], %i4");
asm(" nop");
asm(" mov %i4, %sp");
asm(" udiv %i2, %i7, %i2");
asm(" nop");
exit(0);
}
Looks like the use of umul/udiv causes an attacker controllable value to be written into the address stored in %sp. Since umul/udiv were emulated instructions on the affected systems, I wonder how umul/udiv is handled on the sun4c ports of linux/*BSD. I suppose if you are still using a sun4c, you will stop attackers simply by boring them to death.
No Comments
Thomas Ptacek | February 17th, 2006 | Filed Under: This Old Vulnerability
Each week on This Old Vulnerability we try to bring you description of a software vulnerability of Significance. For example, last week’s inaugural episode described Loadmodule2, a cat-and-mouse classic in which 8lgm beat Sun’s IFS environment resetting countermeasure by simply creating two IFS variables. That’s a vulnerability we can file under “clever”.
On today’s episode, we bring you a vulnerability we can file under “sick”: the wu/bsd FTPD signal race.
FTP is a scary protocol. It allows users to upload and download files from remote servers. Non-credentialed Internet users can interact with an FTP server by logging in as “Anonymous”. FTP servers naturally take safeguards to limit what anonymous users can do. In 1997, the state of the art in FTP security countermeasures was to “downgrade” privileges from “root” to “nobody” and chroot the server to an anonymous FTP jail, in which “anonymous” has no privileges to write files.
Unfortunately, for no reason that remained valid in 1996, the FTP protocol introduces needlessly complex connection handling drama. The details we’ll save for a different show (“this old protocol”?), but, suffice it to say, a server managing a single anonymous FTP login has to manage many individual connections. Not only that, but, because FTP is a protocol designed before the select() system call, it uses TCP URG to deliver command-and-control traffic.
Here’s what you need to know about TCP URG to understand the FTP signal race: an application that cares about URG tells the kernel to deliver a signal (SIGURG) when an URG segment is received.
(Here’s what else you need to know about TCP URG in any other situation: nothing).
Here’s what you need to know about signals to understand the FTP signal race: in normal BSD socket code, the receipt of a signal causes a process to perform the moral equivalent of spawning a new temporary thread of control. In FTPD, when SIGURG was received, that thread’s job was to longjump the server back to the command loop to process the new incoming command.
This wouldn’t be a problem except that FTPD also used signals to gracefully handle connection loss. If you abruptly closed one of your FTP connections, the server would get SIGPIPE. It would handle SIGPIPE by performing a logout operation on your behalf.
Here’s what you need to know about FTPD’s logout routine to understand the FTP signal race: it restored the server’s effective UID back to root.
Here’s what happened when a certain Mac FTP client terminated a download by both closing a connection and sending the “ABORT” FTP command to the server: it got silently logged in as root.
More specifically:
- Closing the data connection generated caused the server to receive SIGPIPE.
- SIGPIPE caused the server to try to log the client out, restoring the UID to 0 to allow it to clean up. But, just before the server process could exit(),
- The “ABORT” command, in a TCP URG segment, arrived at the network stack, generating a SIGURG that bounced FTPD out of the SIGPIPE signal handler and into the SIGURG signal handler, which
- handled the ABORT command by restoring the server process to the FTP command loop to handle the next command.
This was a fun vulnerability check to write (I wrote the Ballista check for it). It worked everywhere, and FTP banners were a poor predictor of it. It’s a race condition, so it takes many (many) attempts to get it right. But you could exploit it with a GUI FTP client just by clicking the “cancel” button a bunch of times.
Here’s more paranoia about Unix signal handling, much of which applies to concurrency in general.
Brought to you in part by a grant from the Jon M. Olin Foundation. Major underwriting for Matasano Chargen is provided by Archer Daniel Midland Company. ADM: Feeding A Hungry World. And of course, readers like you!
1 Comment
Dave G. | February 6th, 2006 | Filed Under: This Old Vulnerability
We have decided to introduce a new blog feature called ‘This Old Vulnerability’. The goal of this is to acknowledge vulnerabilities that were either monumental or clever. We will begin this series with a vulnerability discovered by 8LGM back in 1995, and falls under the clever category.
8LGM was one of the first (maybe even the first) vulnerability research teams to publish advisories on mailing lists like bugtraq. They performed a lot of pioneering research (primarily on SunOS 4.x and later Solaris 2.x), including some of the first buffer overflows (e.g. the infamous syslog() overflow exploited via sendmail). One of their most clever vulnerabilities involved a seemingly patched version of the setuid root loadmodule command. It had previously been vulnerable to a classic system() IFS hack, which had supposedly been fixed.
Unfortunately, Sun’s solution was to simply reset IFS using a function like putenv(). 8LGM’s response was to simply create two IFS variables before calling loadmodule. Exploit and advisory are still available.
No Comments