Friday, January 18, 2008

Why all good Developers and penetration testers should "Know thy API"

Trawling through an API always exhibits interesting results. A vital motto of Developers and respectable penetration testers should be "know thy API". As a Developer I will rely on the API to aid validation and at the same time I should be aware of any "gotchas" that can lie in the undergrowth when creating an Object, for example values which can be passed during instantiation that you would not normally expect. As a penetration tester I will use anomalies to my advantage to circumvent validation routines.

Knowing the values which can be used to instantiate certain Objects can yield interesting results. Let's take the java.math.BigDecimal class as an example as it is an Object I would expect to be used when testing financial applications. There have been many occasions when the "exponent hack" has come in useful as it can be used to bypass validation routines which in turn results in overflows, being able to create values less than 1 (without starting with zero or using decimal notation), and a wide range of other exceptions / unexpected behaviour when combined with other components.

I have seen Developers attempting to validate a number based on length of the string (shocking but true!). For example, it was assumed that if the length of the string was less than or equal to 4 then the number could not exceed 9999. We could envisage the code something along the lines of:

String sNumber = request.getParamater("numberNoMoreThan5Char");

//Make sure the number is less than 9999 and greater than 0.
if(sNumber.length() <= 4 && sNumber.charAt(0) != "0")
BigDecimal myNumber = new BigDecimal(sNumber);


The use of scientific notation will allow us to bypass this poor validation routine (the goal here is to instantiate BigDecimal and not to result in a NumberFormatException, which can be easily achieved). For example, if "numberNoMoreThan5Char" is set to "1e10" we meet the validation requirements as the string is equal to four characters and does not begin with zero. However, BigDecimal is then instantiated with with a value of 10000000000. Similarly, by passing "1e-9" results in the BigDecimal being instantiated with the value of 0.000000001. As expected, this will cause further complications throughout the application and will most likely lead to data degradation i.e data which is stored that would have never been expected.

A second example can be seen with the java.lang.Double class. A technique which is often used to determine if a number is valid (I found this code in the OWASP ESAPI project) goes along the lines of:

public boolean isValidNumber(String input)
{

try
{

Double.parseDouble(input);
}
catch (NumberFormatException e)
{

return false;
}
return true;
}



Now scientific notation can be used here and of course this isn't a problem as such notation results in a valid number. But before we proceed let's quickly delve into the Java API documentation and take a look at the explanation of Double.parseDouble(String):
parseDouble
public static double parseDouble(String s) throws NumberFormatException
Returns a new double initialized to the value represented by the specified String, as performed by the valueOf method of class Double.

Parameters:
s - the string to be parsed.
Returns:
the double value represented by the string argument.
Throws:
NumberFormatException - if the string does not contain a parsable double.
Since:
1.2
See Also:
valueOf(String)

It may therefore come as a surprise that passing a string with the value "NaN" (not-a-number) or "Infinity" will result in isValidNumber returning true. For example, Double.parseDouble("NaN") or Double.parseDouble("Infinity") is perfectly valid and actually returns a Double with a value set to "NaN" or "Infinity" and in a lot of situations is not what a Developer would expect or want for that matter. This is a perfect example of what happens when Developers rely on an API to perform validation without knowing the anomalies. A little investigation reveals how we are able to pass "NaN" and "Infinity" as a valid argument. Let's take a look at the code for Double.parseDouble(String):


public static double parseDouble(String s) throws NumberFormatException
{
return FloatingDecimal.readJavaFormatString(s).doubleValue();
}

Yep, just one line of code! Well it appears we will have to dig down just a little further and check out the FloatingDecimal class and see what resides in the method readJavaFormatString(String). As it turns out, this method is 249 lines long! So I have selected the interesting piece from the method:

// compare Input string to "NaN" or "Infinity"
int j = 0;
while(i <>
if(in.charAt(i) == targetChars[j]) {
i++; j++;
}
else // something is amiss, throw exception
break parseNumber;
}


// For the candidate string to be a NaN or infinity,
// all characters in input string and target char[]
// must be matched ==> j must equal targetChars.length
// and i must equal l
if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
return (potentialNaN ? new FloatingDecimal(Double.NaN) // NaN has no sign
: new FloatingDecimal(isNegative?
Double.NEGATIVE_INFINITY:
Double.POSITIVE_INFINITY)) ;


As we can see from the code comments it is clear that it has been designed to take "NaN" and "Infinity" as a valid argument. Developers can be forgiven for not expecting such values to be valid as it was not directly mentioned in the API documentation for parseDouble(String) as we saw above. Although there are actually some clues as the documentation did mention:

See Also:
valueOf(String)

As a Developer I find it vital that I need to be aware of such anomalies to keep the code well validated and will often find myself digging deeper down the Java package tree so I can manually check for anything unexpected, I can then tweak my validation accordingly and combine such details to construct a more intelligent alerting log system (if I saw the anomalies passed to my application it would make me very suspicious). As a penetration tester I will use these anomalies as a means for attacking an application, and as we have seen such techniques come in extremely useful.





Tuesday, January 15, 2008

OWASP - Java Gotchas

As I spend more time developing in Java and analysing others source code for quality and security issues I come across some common pitfalls that often catch Developers out, some which can have serious consequences on the logic. From time to time I rip open some of the Java classes developed by Sun to get a deeper understanding as to what goes on behind the scenes. There is a particular topic that I enjoy contributing to on OWASP called Java Gotchas (unfortunately not as much as I would like to). If Java is your thing I am sure you will find something on there of interest and of course please feel free to contribute.

Monday, January 14, 2008

“If you’re not sure what you’re about to run, then don’t click Run!”

Note: When I use the term “users” in this article I am reflecting upon my experiences with technical and non-technical users.

When something is a mystery how can you be expected to know what the best response would be? This is why it is important to adopt best practices to prevent falling into nasty traps. The general rule of thumb is not click “OK” or “Run” if you don’t know what it is or where it came from.

Having somewhat of an unhealthy obsession with Java I want to correct the misconception that Java is “safe”. Now, I am not talking about vulnerabilities such as buffer overflows as these problems are rare due to them existing, for example, when JNI is used and then in which case it is not really the fault of the JVM.

The focus of this discussion concentrates on the functional capabilities of Java and the common misconceptions; this can also apply to other development kits for that matter. Anyone who is familiar with Java will know that it is has a rich API and there really aren’t any functional limitations. I believe the misconception of Java being “safe” has emerged due to the lack of association with malware. But a tool or development kit is only as safe as the intentions from the user or developer.

I find it surprising that Java has not become a greater focus for performing malicious activities such as a mechanism to deliver payloads. With the misconception of Java safety and the fact that it is not a primary focus for the anti-virus industry it would seem like an ideal combination for malicious use. Let’s face it, Virus Analysts specialise in lower level languages such as Assembly and C++, not Java.

So as an example let’s explore the world of Java applets. Users often feel a false sense of heightened security when using a web browser, even more so when confronted with a Java applet. When it comes to Java applets they can be considered secure in a lot of respects due to them being constrained to a sandbox environment but signed Java applets can perform the equivalent of Java desktop applications. It is a trivial task to sign your own applet, a quick Google search will present you plenty of examples (although I will show you how I signed my applet in a minute)

The core of the problem lies with users accepting signed Java applets, we see the same problem when users execute attachments from emails. However, users are becoming increasingly cautious of email attachments but I the same is not true for signed Java applets. The following video demonstrates the capability of a signed Java applet.....

It's currently hosted here, but the video quality is a bit trashed. It is more worthwhile downloading from here:

http://rapidshare.com/files/85112606/Dont_click_Run.wmv.html

Note: The applet was signed using the following commands:

Step 1: jar cvf NotepadApplet.jar NotepadApplet.class

Step 2: keytool -genkey -alias signFiles -keystore compstore -keypass kpi135 -dname "cn=Adam Boulton's Applet Patcher" -storepass 123456

Step 3: jarsigner -keystore compstore -storepass 123456 -keypass kpi135 -signedjar TheSignedNotepadPatcher.jar NotepadApplet.jar signFiles

Step 4: keytool -export -keystore compstore -storepass 123456 -alias signFiles -file Notepad.cert



Saturday, January 5, 2008

A new beginning....

As a new year's resolution I decided it was about time to make my research available on a global basis. This blog will focus around my core skills and interests in software development (mostly Java and Assembly), reverse engineering and other aspects surrounding IT security, such as "in the wild" hacking techniques. I look forward to all feedback, now let's get down and dirty and have some phun. Of course the first blog post always has to finish with the classic message

BA0C01B409CD21B44CCD210048656C6C6F20576F726C64210D0A24
(Copy and paste into hex editor and save as a .com file)

Cheers

Adam
http://www.linkedin.com/profile?viewProfile=&key=12090735