Insider attacks and static analysis:How to spot the signs with three important new analysesTweet
UnrealIRCd is an open-source Internet Relay Chat server that is very widely deployed worldwide. As it is such a popular server, it is not surprising that hackers consider it a rather juicy target. On the 12th of June, 2010 a member of the server support team posted a message to the mailing list concerned with its security. The message began:
I'd like to let you know that there's been a compromise of the unrealircd website and ftp and the 188.8.131.52 tarball release had been replaced by a backdoored copy.
Somehow an unknown party had surreptitiously replaced the official download tarball with a version that contained a deliberately inserted backdoor that allowed an attacker to execute arbitrary code on the server machine. The replacement had apparently been done some time in November of the previous year, so the vulnerability had been in the wild for over six months. The report of this defect made it into the CVE database as CVE-2010-2075.
I can only imagine the sick feeling the developers must have experienced when this came to light. Through no fault of their own they were being exploited for nefarious purposes. Even though the developers took security very seriously, their safeguards and checks and balances were completely bypassed.
There is absolutely no evidence or even suggestion that the attack was mounted by any of the developers of the software. It is probable that the attacker took advantage of a weakness in the configuration of the download server to replace the official tarball with their own corrupted version. Nevertheless, this attack has some similarities to insider attacks. Insider attacks often take the form of vulnerabilities that are deliberately inserted into the code. The attacker usually takes precautions to hide the intent by obfuscating their edits.
How can insider attacks be detected? The Command Injection Checker
We have been thinking about how to detect insider attacks recently, and have new functionality in CodeSonar 4 to support finding them, so it is instructive to look back at that code and see how a static analysis tool might have been used to find the vulnerability.
Any code defect that allows an attacker to execute arbitrary commands is usually referred to as a code injection error. When we run CodeSonar on this code it reports a Command Injection warning. A screenshot of the report is shown below.
At first glance, this code looks fairly innocuous. The defect is being reported on line 1436 at the invocation of DEBUG3_LOG. A reader with no reason to suspect this code is malicious is unlikely to see much wrong with it.
Take a look at the info pane on the bottom right, however. It shows that DEBUG_LOG3 is a macro. When we expand the definition of the macro inline (pictured below), we can see that it uses a different macro DEBUG_DOLOG_SYSTEM, which in turn expands to a call to system().
Now the intent is clear. If the condition is satisfied, then the string in readbuf is passed to system(), which executes it as a process with the same privileges that the server is executing with. The next question to ask is how can the condition be satisfied? It involves comparing the first two characters of the string against DEBUGMODE3_INFO. This is a macro that expands to the string "AB". Thus an attacker can exploit this by sending a string like "AB; rm –rf /". The "AB" will fail, but the second command will attempt to delete all the files in the root directory.
The Command Injection checker in CodeSonar is new in version 4. It takes advantage of the new taint analysis functionality. Taint analysis tracks the flow of potentially hazardous information from the points where it originates (taint sources), to the points where it can cause damage (taint sinks). There are different kinds of taint based on where the information is coming from, and depending on how the program is deployed, some kinds can be benign. In the example above, the taint kind is network taint, which for a server of this kind is probably the most hazardous kind. Other kinds of taint include file system, environment, clock, and even DNS record.
The red underlining shown in the warning listing indicates that the value is potentially tainted. When a user hovers the mouse over the associated token, a popup shows the kind.
Another way to spot attacks: Visualized tainted data flow analyses
There is another way of viewing the taint properties of the program; a metric derived from the number of taint sources and sinks can be overlaid on a visualization of the structure of the program. In the visualization below, the top-level boxes represent source files and the lower level boxes represent individual functions; the lines represent function calls.
In this visualization, the intensity of the red indicates the value of the taint sources metric. From this it is easy to judge the attack surface of the application. A source-code security auditor looking at this code will want to immediately go to the parts that generate tainted information to understand whether it can flow to sensitive areas without being checked for validity first.
In this case the file s_bsd.c towards the top is one of the top three sources of taint. Focusing in on this shows the functions within that are responsible.
In the view above, I have selected a different layout and changed the display so that the intensity of the blue glow is proportional to the value of the taint sink metric.
The function read_packet() is the one where the command injection vulnerability was found. As can be seen, it attracts attention because it is one that involves both taint sources and taint sinks.
Binary analysis for finding attacks
Finally it is worth pointing out that the same command injection defect can also be found by our binary analysis tool. CodeSonar's binary analysis technology is capable of analyzing stripped optimized executables; roughly speaking, it finds the same class of defects that can be found in the source code. Our new integrated analysis is capable of analyzing source and binaries simultaneously. This is useful in cases where you have source code for most of the project, but only binary libraries for some components.
In this case we have analyzed the executable created by compiling UnrealIRCd. A screenshot of the warning report is shown below.
In one sense it is actually a little easier to understand this vulnerability in the machine code because the obfuscation using the preprocessor has been stripped away. Whereas the source view looked like a harmless invocation of a macro, here the call to system() sticks out like a sore thumb.