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.