Reviewing Java source code can pose a challenge for a security auditor, as methods used to exploit programs in C or C++, namely memory corruption bugs, are mitigated by Java itself, which hides the details of memory management from the programmer. This same tendency to hide implementation details with a layer of abstraction leads to an entire class of common Java programming errors which can have a critical impact on the security of the application.
Java vulnerabilities are most commonly found in places where unsanitized user input is passed, directly or indirectly, on to an underlying library or service. To put it another way, vulnerabilities aren’t found in the Java code itself, they are found by following user input through the Java source and out the other side.
The tendency of Java to hide implementation details from the developer actually creates these vulnerabilities in places where it might not otherwise exist. Java developers use wrapper libraries for backend services, such as SQL or LDAP, and assume that they automatically sanitize their inputs, when usually they do not. In most cases, Java wrapper libraries themselves are simply classes that store and manipulate strings which are just passed directly on to the wrapped service. In many of these implementations, such as the ORM library Hibernate, there are architectural reasons why this behavior can not be changed.
In this post, I will describe a class of extremely common Java vulnerabilities, specifically these “pass-through” bugs, characterized by user input passing directly through Java unexamined.