lang

Code injection with Java Proxy example

I was using JDBC PreparedStatement’s batch updates to modify a lot of data in a database and the processing was failing for one of the batch updates because of integrity constraint violation. The exception didn’t contain enough information to find out which data caused the failure and so I’ve created a dynamic proxy for the PreparedStatement that remembered values passed into each of the batch updates and in the case of a failure it automatically printed the batch number and the data.

The crucial part of the code:

LoggingStatementDecorator.java – snippet 1

class LoggingStatementDecorator implements InvocationHandler {
 
   private PreparedStatement target;
   ...
 
   private LoggingStatementDecorator(PreparedStatement target) { this.target = target; }
 
   @Override
   public Object invoke(Object proxy, Method method, Object[] args)

   throws Throwable {
 

try {

   Object result = method.invoke(target, args);

   updateLog(method, args); // remember data, reset upon successful execution

   return result;

} catch (InvocationTargetException e) {

   Throwable cause = e.getTargetException();

   tryLogFailure(cause);

   throw cause;

}
 
   }
 
   private void tryLogFailure(Throwable cause) {

if (cause instanceof BatchUpdateException) {

   int failedBatchNr = successfulBatchCounter + 1;

   Logger.getLogger("JavaProxy").warning(


   "THE INJECTED CODE SAYS: " +


   "Batch update failed for batch# " + failedBatchNr +


   " (counting from 1) with values: [" +


   getValuesAsCsv() + "]. Cause: " + cause.getMessage());

}
   }
...

Notes:

To create a proxy, you first need to implement an InvocationHandler and its invoke method, which is called whenever any of the interface’s methods is invoked on the proxy

You can access the information about the call via the java.lang.reflect.* objects and for example delegate the call to the proxied object via method.invoke

We’ve also an utility method for creating a proxy instance for a Prepared statement:

LoggingStatementDecorator.java – snippet 2

public static PreparedStatement createProxy(PreparedStatement target) {
  return (PreparedStatement) Proxy.newProxyInstance(

PreparedStatement.class.getClassLoader(),

new Class[] { PreparedStatement.class },

new LoggingStatementDecorator(target));
};

Notes:

  • You can see that the newProxyInstance call takes a classloader, an array of interfaces that the proxy should implement, and the invocation handler that calls should be delegated to (the handler itself has to manage a reference to the proxied object, if it needs it)

It is then used like this:

Main.java

...
PreparedStatement rawPrepStmt = connection.prepareStatement("...");
PreparedStatement loggingPrepStmt = LoggingStatementDecorator.createProxy(rawPrepStmt);
...
loggingPrepStmt.executeBatch();
...

Notes:

  • You see that we have to manually wrap a raw object with the proxy and use the proxy further on

Related Article:

Reference: Practical Introduction into Code Injection with AspectJ, Javassist, and Java Proxy from our JCG partner Jakub Holý at The Holy Java blog

Byron Kiourtzoglou

Byron is a master software engineer working in the IT and Telecom domains. He is an applications developer in a wide variety of applications/services. He is currently acting as the team leader and technical architect for a proprietary service creation and integration platform for both the IT and Telecom industries in addition to a in-house big data real-time analytics solution. He is always fascinated by SOA, middleware services and mobile development. Byron is co-founder and Executive Editor at Java Code Geeks.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button