Format string vulnerability found in 'sudo'
sudo.ws
sudo.ws
Here's how it breaks down
For reference, here's the basic idea of Memcpy on x86
movl LEN(%esp), %ecx
movl SRC(%esp), %eax
movl DEST(%esp), %edx
So you the general premise of exploiting format string bugs if you've never seen them before (and if you're a young person like myself, It's entirely possible this is the first C format specifier bug you've ever seen in a major piece of software, yet again, Finite Field analysis scores another victory for the Static Analysis Team. Take that fuzzers!) is to either use clever format specifiers (%X, and %N as mentioned above are some old school faves) or to take advantage of lower system calls like brk() that can be indirectly abused through calls that accept format specifiers as an argument, but I digress.So, the user arguments are stored in the above registers. To exploit this vulnerability, you must have control of the length argument which is stored in ECX general purpose register as you can see from this code snippet.
cmp %eax, %edx
jx link(copy_forward)
je L(fwd_write)
cmp $32, %ecx
jge L(fmt)
jmp L(get_prog_name_offset)
So, the user arguments are stored in the above registers. Before things like ROP, to exploit these vulnerabilities the attacker must have control of other, more directly meaningful arguments such as EIP (Which if you control EIP, why bother setting up some complex staged format string exploit?) and hoped that an external task would reboot this binary if it crashed, and keep trying until you beat address space layout randomization at the entropy game, again, I digress. Regardless, The format specifier returned from getprogname() allows us to do some funky stuff like use "safe" format string specifiers like %c (Don't you just love that classic Infosec industry model where %x is 'dangerous' but %c is 'safe' and where breaking MD5 is a big deal but nobody checks the integrity of their login scrips?) to pop bytes off the stack, write an address either to a stored instruction pointer that will be invoked later in the runtime of the program (and presumably will repair the stack before anything gets noticed by the OS) or to just get trashy and munge your local stack with a new EIP pointing to your shellcode (You can even have Null bytes in it, We're moving on up!). Of course, you're also going to have to be attacking a system running a filesystem with very, very, very long filenames, but I most modern ones support around 255 byte filenames, which is definitely not enough if you're using %c, but you could definitely exploit this bug with %o with a limit of 255 bytes.The remaining, perhaps more difficult question still has to be asked -- Why is nobody taking compiler warnings seriously? Do you think compilers are just kidding when they say "Someone will use this to take control of any system that has this software"?
easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
va_start(ap, fmt);
vfprintf(stderr, fmt2, ap);
va_end(ap);
efree(fmt2);
Obviously, fmt2 can still contain a format string, yet it is printed anyway with vfprintf. I'm really surprised this type of bug still exists. Doesn't every decent compiler warn the developer about this? -Wformat is included in -Wall. For more control over some
aspects of format checking, the options -Wformat-y2k,
-Wno-format-extra-args, -Wno-format-zero-length,
-Wformat-nonliteral, -Wformat-security, and -Wformat=2
are available, but are not included in -Wall.The bug is when getprogname() also returns a string containing a format specifier (e.g. "%s"), which is not expected.
Clearly the fix is:
fprintf(stderr, "%s: ", getprogname());
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
(Edit for formatting, clarity)http://dev.mysql.com/doc/refman/5.0/en/mysql-real-escape-str...
I'm sure what you meant was a server-side escaping function which is obviously pointless, but I did want to point out that MySQL's client driver does ship with one that you can use so you don't have to write your own.
At least in Perl, there's no need to escape placeholder values explicitly. I believe the prepared statement is stored on the server, and then the values sent later. Of course the escaping could be the work of the driver.. anyone know?
Prepared statements are disabled by default and require MySQL >= 4.1.3. Instead, the driver does the placeholder replacement on the client, and prepare() does nothing clever at all.
If you don't want to use a format string, use a function that takes a regular string, like puts, instead of a vprintf variant. Why would anyone go to the trouble of escaping a format string so they can use it with a function whose sole purpose is to parse format strings? (Which you can already do, by the way, by using vprintf correctly.)
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 10.04.3 LTS
Release: 10.04
Codename: lucid
$ sudo -V
Sudo version 1.7.2p1 $ ln -s /usr/bin/sudo ./%s
$ ./%s -D9
[some debug output with garbage]
Segmentation fault
$
Bug is here:https://bugs.gentoo.org/show_bug.cgi?id=401533
Looks like it's patched on x86/amd64 already.
OpenIndiana looks unaffected. It's using 1.7.4p4.
Fedora compiles everything with -DFORTIFY_SOURCE which means this still crashes, but is not (thought to be) vulnerable. In any case there is an update available for Fedora right now. https://admin.fedoraproject.org/updates/sudo-1.8.3p1-2.fc16
/me sends a note to the package maintainers anyway.
Still in beta though. Not very stable.
It is still pretty new, and from what I understand upgrading can be a bit of a pain, but pacman 4.0 has package signing.
Been using Fedora for a bit now, so haven't actually tried it yet...