Help!!! Developers are going blind from Log Files!
This is a post by Sri Mallur, an instructor with the SANS Institute for SANS DEV541: Secure Coding in Java EE: Developing Defensible Applications. Sri is a security consultant at a major healthcare provider who has over 15 years of experience in software development and information security. He has designed and developed applications for large companies in the insurance, chemical, and healthcare industries. He has extensive consulting experience from working with one of the big 5. Sri currently focuses on security in SDLC by working with developers, performing security code reviews and consulting on projects. Sri holds a Masters in industrial engineering from Texas Tech University, Lubbock, TX and an MBA from Cal State University-East Bay, Hayward, CA.
Recently one of my consultants called me frantically saying that a log forging fix had rendered log files useless. Apparently the developers were going blind trying to look at the log files.
First let us at least get a baseline about what log forging is and its importance. Generally most developers roll their eyes when a security consultant talks to them about log forging. Trust me, log forging is important, maybe, not to you (read developer), but, it is to the business. By the end of this post, hopefully you will see why.
What is Log Forging - and Why is it Important?
Simply put, log forging is the ability of an adversary to exploit an application vulnerability and inject bogus lines in application logs. "Why would he want to do this?", you ask. Let's put the security issue aside for a minute. Imagine, you a developer just got assigned a bug on code running in production. Where would you go first to start your triage process? The logs. But what if the logs you are relying on aren't real and have bogus entries? You see random lines about Database Down and then Database Up and other events that don't make sense. You get the picture. It's possible that you'll climb up the wrong tree trying to solve the production mystery or pursue such a convoluted path that it leads you to hitting the bottle to bury you ineptitude. You know this to be true ?
Now let's get serious. A hacker will create log entries for the same reasons that I just spoke of: to confuse the security police (read forensics, incident handlers or what not). Security folks refer to logs as "discovery control": they use logs to discover bad things, to figure out what happened and the mechanics of how it happened so we can plug the hole. Without the ability to discover the mode of attack, our applications will remain vulnerable.
There's another thing that we security folks like to do once in a while and we call that "attribution". We would like to catch the person(s) who did something bad and seek justice. And, yes log files are legally admissible documents that lawyers use to argue the case. But, the fact that our log files are tampered does not stand the intense scrutiny of defense lawyers and this evidence is thrown out, making the case less strong. Adversaries generally go unpunished because we failed to protect our log files.
So, I hope I have convinced the developer in you that log forging is not just some obscure security issue that security consultants approach you about so they can stay busy. They in fact approach you because it matters to you and the business (remember triage, false entry). We want to make sure that when you use log files to triage an issue, you can depend on the logs.
Preventing Log Forging.. and Going a Little Too Far
Now that we have dealt with what log forging and why it matters, let's continue with my story. An engineer had decided to write his own adapter to prevent log forging (it's a long story why he had to write his own, I won't go into it here, needless to say he had to.) Keep in mind that to prevent log forging all he has to do is prevent new line characters. Preventing new line characters will ensure that the adversary cannot create new lines of forged entry. Generally this is what I would expect to see in code to prevent a new line character:
... String clean = message.replace( '\n', '_' ).replace( '\r', '_' ); ...
The above line of code will sanitize the input by replacing CRLF with underscores. This is enough to prevent log forging. (BTW: OWASP ESAPI's Log Forging class already has this built in).
But the the developer got a little fancy and added the following line in his class:
... clean = ESAPI.encoder().encodeForHTML(message); ...
The above line of code in addition to sanitizing the input also htmlencoded the input before writing to the log file. Security conscious developers know that we encode our output to prevent Cross-Site Scripting. This extra line of code would have worked well if the developers were viewing the log files in a browser and the browser interpreted the htmlencoded data appropriately. But in our case, those poor developers using the logs were viewing the text files directly and we were asking them to manually process all those html encodings!!!!. No wonder they were going blind.
Imagine a line like this:
[Error] 04-09-2013 Login failed for Admin
xb;ERROR] 04-09-2013 Login Failed for Admin (Encoded)
You can already see that this simple line almost becomes unreadable and imagine a file full of such hash/html encodes.
The fix was of course to comment out the line that was encoding the input before writing to the file. I want to make sure I clarify the fix. We would want to encode the input if the file was being viewed in a browser (like some log aggregators do) to prevent cross-site scripting (running scripts from the log file while viewing them). But in our case, developers were viewing the log files as a text so the encoding was not required.
This is a case of incomplete understanding of the issue and therefore the fix was incorrect. Our engineer of course is a smart guy and wished well but this was a great learning moment for all of us.