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.