Migration to an easier environment

In my previous post I mentioned that I got the Evil bit set. But I had to do that the long way round, as in, I actually changed the code in the OpenJDK of the following classes:

  • java.lang.String
  • java.lang.AbstractStringBuilder
  • java.lang.StringBuilder
  • java.io.BufferedReader
  • java.io.PrintStream

My PoC worked, but for every change I build into it, I had to wait for about 20 to 25 minutes on the compilation step. Which, of-course, for me is unacceptable but it did show that my initial feeling around the tainted String was correct. So now I made a newer version in which I use Javassist to build the modified classes based on the used JDK.

        ClassPool cp = ClassPool.getDefault();
        CtClass cc = cp.get("java.lang.String");

        // add the new tainted field
        CtField f = new CtField(CtClass.booleanType, "tainted", cc);
        f.setModifiers(Modifier.PRIVATE);
        cc.addField(f);

        // generate getters and setters for the new field
        cc.addMethod(CtNewMethod.getter("isTainted", f));
        cc.addMethod(CtNewMethod.setter("setTaint", f));
        cc.writeFile(destPath);

This removes the dependency to my build version, but allows anybody to create their own SecureRT.jar file (ok, modified classes for now) and test their applications on the potential use of tainted strings.

The EVIL bit has been set

Today I finally managed to create a PoC in which an exception is thrown based on the presence of the evil bit. I used to PoC as described in my previous post and got it working.

Exception in thread "main" java.lang.RuntimeException: Tainted
	at java.io.PrintStream.print(PrintStream.java:666)
	at java.io.PrintStream.println(PrintStream.java:807)
	at SimpleTest.main(SimpleTest.java:15)

So, what did I do.
So far, all my attempts were unsuccessful as other exceptions kept popping up (as in, not the desired one) so I went to the core of Java. I modified the OpenJDK code and added the ‘evil’ bit to the String class (with getters and setters of course):

transient boolean tainted = false; //RFC3514 compliant

To be able to acknowledge that you can’t trust the information that was read from System.in, I modified BufferedReader.readLine to be as follows:

    public String readLine() throws IOException {
        String result = readLine(false);
        if (result != null)
        result.setTaint(true);
        return result;
    }

To check if tainted data is written to the System.out I modified PrintStream.print(String) to the following:

    public void print(String s) {
        if(s.isTainted()) { throw new RuntimeException("Tainted");}
        if (s == null) {
            s = "null";
        }
        write(s);
    }

This will only work when you print the String as is, however, in my PoC I prepended a welcome text to the String which meant that I had to adjust StringBuilder as well to propagate the taint. First in AbstractStringBuilder

    public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        this.tainted |= str.isTainted();
        
        return this;
    }

but also in StringBuilder itself

    public String toString() {
        // Create a copy, don't share the array
        String result = new String(value, 0, count);
        result.setTaint(tainted);
        return result;
    }

These changes are then compiled and bundled into a secure rt.jar file. Using this jar file meant that I now could do a basic taint tracing. The PoC runs as previously described, but if you run it with the secure RT.jar file the exception will be raised (as shown above).
Nice.

A new approach

Thanks to Arshan Dabirsiaghi who made a comment in http://blog.diniscruz.com/2013/09/java-tainted-strings.html I got a new approach to investigate. He mentioned JRebel and their process which reminded me of the Javaagent – which I had completely forgotten. JRebel uses the Instrumentation possibility to rewrite classes to be updateable, so I’m going to use the same technique to add tracking information into Strings.

I already have created an simple test case of input validation and output encoding:

package org.owasp.securert;

import java.io.*;

public class Basetest {
    public static void main(String[] args) {
        System.out.print("Enter your name: ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String userName = null;
        try {
            userName = br.readLine();
        } catch (IOException ioe) {
            System.out.println("IO error trying to read your name!");
            System.exit(1);
        }

        System.out.println("Thanks for the name, " + userName);
    }
}

I agree, it’s not a highly sophisticated test case, but it has security vulnerabilities. If you send the following string

'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08test                           ' 
it will print Thanks test
instead of Thanks for the name, test that you would expect.

Now I’m going to see how ‘easy’ it will be to track the taint using both approaches, Bootclassloader and Javaagent.

Up the ante

My goal with the String meta-data is actually very simple. It should be designed in such a way that all developers/testers that are using the JVM can use it. Sort of copied from the ZAP policy “It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing as well as being a useful addition to an experienced pen testers toolbox.”

The end result should be easy to use and non intrusive to existing code. For this reason I’ve started to focus on the option of customisation. If I manage to adapt the Core classes of Java in such a way that I can do taint tracing, I can create a version in which security tests can be run simultaneously to unit and integration tests.

By allowing that the security testing is executed during unit and/or integration tests that would mean that ‘ordinary’ developers can perform these tests without those pesky security testers. And by changing the base classes themselves, it would mean that the test would be non intrusive to the actual code created by the developers in the first place.

The changed base classes should not be used in production systems, but if I manage with this, perhaps those production systems would be a bit more secure.

Where to start

As described in my previous post, I want to add meta-data to a String in Java. This meta-data should be used for example to mark a String as tainted (contains not validated text) from a security perspective. Unfortunately it isn’t as simple as it sounds as the Java String class has various ‘exit-points’ for it’s value, a.k.a. just marking the String class might not be enough.

We (Dinis Cruz and me) have a couple of options to investigate:
1. Customize the String class and add the taint mark to it. This means that a custom bootstrap is needed to be able to use the adapted String class.
2. Using AOP and try to make a note of the char array within the class and follow that.
3. Use JNI or JNA and mark the char array in a way.
4. Add information to the char array in memory to indicate that it contains tainted data.
There maybe other options, but we’re not aware of those (yet).

I do know that it will add tremendous value to a security test if we can demonstrate if tainted data flows through the application. This is the basis of a potential vulnerability, and if we can demonstrate this to the developers it might be mitigated before it can be abused.
  
Lets see if we can make this work.

It starts with an idea

The AppSec conference in Hamburg just stopped and I’m already busy again. But this time it’s not only with the CTF that I host for OWASP, but also with a new – at least I hope it’s new – idea.
And that is to improve the security position of Java. The idea is to add meta-data (like a taint flag) to the String class and by doing so manage to get source-sink tracing possible. I’m not doing this alone, but together with Dinis Cruz we’re looking into this possibility. Not to make a production alteration, but as an additional scenario during testing.
As John Willander already said, the String class is way too open for abuse. Let’s find an easier way to check this and by doing so improve the code quality.

There is nothing wrong with being ambitious.