If you have a few years of experience in the Java ecosystem, and you're interested in sharing that experience with the community (and getting paid for your work of course), have a look at the "Write for Us" page. Cheers. Eugen

If you’re working with Spring, check out "REST With Spring":

>> CHECK OUT THE COURSE

1. Overview

In this quick article, we’ll explore one of the most common security issues in JVM world – Log Forging. We’ll also show an example technique that can protect us from this security concern.

2. What Is Log Forging?

According to OWASP, log forging is one of the most common attack techniques.

Log forging vulnerabilities occur when data enters an application from an untrusted source or the data is written to an application/system log file by some external entity.

As per OWASP guidelines log forging or injection is a technique of writing unvalidated user input to log files so that it can allow an attacker to forge log entries or inject malicious content into the logs.

Simply put, by log forging, an attacker tries to add/modify record content by exploring security loopholes in the application.

3. Example

Consider an example where a user submits a payment request from the web. From the application level, once this request gets processed, one entry will be logged with the amount:

private final Logger logger 
  = LoggerFactory.getLogger(LogForgingDemo.class);

public void addLog( String amount ) {
    logger.info( "Amount credited = {}" , amount );
}

public static void main( String[] args ) {
    LogForgingDemo demo = new LogForgingDemo();
    demo.addLog( "300" );
}

If we look at the console, we will see something like this:

web - 2017-04-12 17:45:29,978 [main] 
  INFO  com.baeldung.logforging.LogForgingDemo - Amount credited = 300

Now, suppose an attacker provide the input as “\n\nweb – 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully”, then the log will be:

web - 2017-04-12 17:52:14,124 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300

web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

Intentionally, the attacker has been able to create a forged entry in the application log which corrupted the value of the logs and confuses any audit type activities in future. This is the essence of log forging.

4. Prevention

The most obvious solution is not to write any user input into log files.

But, that might not be possible in all circumstances since the user given data is necessary for debugging or audit the application activity in future.

We have to use some other alternative for tackling this kind of scenario.

4.1. Introduce Validation

One of the easiest solutions is always validating the input before logging. One problem with this approach is that we will have to validate a lot of data at runtime which will impact the overall system performance.

Also, if the validation fails, the data will not be logged and become lost forever which is often not an acceptable scenario.

4.2. Database Logging

Another option is to log the data into the database. That is more secure than the other approach since ‘\n’ or newline means nothing to this context. However, this will raise another performance concern since a massive number of database connections will be used for logging user data.

What’s more, this technique introduces another security vulnerability – namely SQL Injection. To tackle this, we might end up writing many extra lines of code.

4.3. ESAPI

Using ESAPI is the most shared and advisable technique as per this context. Here, each and every user data is encoded before writing into the logs. ESAPI is an open source API available from OWASP:

<dependency>
    <groupId>org.owasp.esapi</groupId>
    <artifactId>esapi</artifactId>
    <version>2.1.0.1</version>
</dependency>

It’s available in the Central Maven Repository.

We can encode the data using ESAPI‘s Encoder interface:

public String encode(String message) {
    message = message.replace( '\n' ,  '_' ).replace( '\r' , '_' )
      .replace( '\t' , '_' );
    message = ESAPI.encoder().encodeForHTML( message );
    return message;
}

Here, we have created one wrapper method which replaces all carriage returns and line feeds with underscores and encodes the modified message.

In the earlier example if we encode the message using this wrapper function the log should look something like this:

web - 2017-04-12 18:15:58,528 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300
__web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

Here, the corrupted string fragment is encoded and can be easily identified.

Once important point to note is that to use ESAPI we need to include ESAPI.properties file in the classpath else the ESAPI API will throw an exception at runtime. It’s available here.

5. Conclusion

In this quick tutorial, we learned about log forging and techniques to overcome this security concern.

Like always, the full source code is available on over on GitHub.

The new Certification Class of "REST With Spring" is finally out:

>> CHECK OUT THE COURSE

Sort by:   newest | oldest | most voted
jmzc
Guest

Thanks. I don’t see the strengh of ESAPI library in that example, because the attack is rejected by .replace() methods

Abhinab Kanrar
Guest

As you mentioned, replace method will only handle injected n,t and r. Apart from that, any abnormal UTF-8 character outside known alphabets will be automatically encoded if we use ESAPI. Just try to run the example from github and you will notice

wpDiscuz