In the first part of this series, I briefly mentioned two inventories of common software weaknesses: the CWE/SANS Top 25 Most Dangerous Software Errors and OWASP Top 10. The OWASP list focuses primarily on Web application attacks and is more a list of attack categories, while SANS 25 focuses on software mistakes that can facilitate an attack. These are excellent resources for developers who wish to think like a hacker and prevent zero-day vulnerabilities in their software.
The software flaw that I will discuss in this article is No. 2 on the SANS 25 list. It is officially known as OS command injection, but is also referred to as shell command injection and remote command execution (RCE).
OS command injection is the most powerful type of weakness because it allows control of the target system. That’s why it’s the first issue my team is trying to locate when we conduct a pen test. As a matter of fact, OS command injection was the principal software flaw used by my team to break into a building automation system, as disclosed in February 2016.
Notorious Examples of OS Command Injection
OS command injections are likely to impact OS components and commonly used libraries that are repackaged with various software. When such flaws are found, their impact is catastrophic because almost all software using that component is also immediately vulnerable.
This was the case with Shellshock, a set of vulnerabilities in the Unix Shell: Bash. Shellshock is maybe the most infamous shell command injection software bug of all. It even earned its own logo:
The Shellshock bug allowed attackers to send arbitrary shell commands to Web servers, network printers and other network software. It also sent system administrators and software manufacturers scrambling to patch their servers.
Because the Shellshock attack code was trivial, hackers immediately created exploits for the issue and began scanning the Internet to take over unpatched servers. This activity started within an hour of the announcement of the vulnerability. Two days later, it was reported that botnets formed from servers compromised by Shellshock were already used in denial-of-service attacks. It is incredible how fast and effective the bad guys can be when given a software bug!
Here is a video demonstrating the Shellshock bug:
https://www.youtube.com/watch?v=bhJmVBJ-F-4
What Is the Programming Flaw?
Let’s take a look at another software bug that was publicized recently. It affects the open-source ImageMagik library, which is used by various Web applications to resize or crop images. The bug, which was dubbed ImageTragik, is only a couple weeks old, but hackers immediately started to exploit it, Ars Technica reported.
The most serious vulnerability from the ImageTragik package is officially known as ‘CVE-2016-3714 – Insufficient shell characters filtering leads to (potentially remote) code execution’. This is almost identical to the SANS 25 name for OS Command Injection: ‘CWE-78: Improper Neutralization of Special Elements used in an OS Command’.
When processing external URLs, the software was substituting user input in an OS command like this:
“wget” -q -O “%o” “https:%M“
|
Scroll to view full table
The %M part is substituted with a user-provided link. If a graphics file contains a link like this:
https://example.com/image.jpg“;|ls “-la
|
Scroll to view full table
Then the software will execute:
“wget” -q -O “%o” “https://example.com/image.jpg“;|ls “-la”
|
Scroll to view full table
As you can see, the hacker can insert his or her own commands to be executed by the ImageMagik library. This is demonstrated in the sample exploit .mvg file.
push graphic-context
viewbox 0 0 640 480
fill ‘url(https://example.com/image.jpg“;|ls “-la)’
pop graphic-context |
Scroll to view full table
How to Prevent Command Injection
The main culprit for command injection is the concatenation of commands with user-supplied input. The best way to prevent it is by using parameterized functions instead, where user input is being passed as parameters rather than the initial command.
Here’s an example of vulnerable code:
char cmd[CMD_MAX] = “/usr/bin/cat “;
strcat(cmd, argv[1]);
system(cmd); |
Scroll to view full table
And here is the correct code using the parameterized function. It’s even less code:
char cmd[CMD_MAX] = “/usr/bin/cat “;
execve(cmd, argv[1]); |
Scroll to view full table
Most programming languages have a way to execute commands through parameterized functions, so you should always try to avoid concatenation. If you must use concatenation, then your best friend is input validation.
Be sure to leverage a white-listing approach and start from the most restrictive character set — for example, alphanumeric. But be careful what you let through. The first fix to ImageMagik introduced input validation, but permitted the ` (back quote) character, which could also be used to inject commands, like so:
Think Like a Hacker
Command injection is an extremely damaging weakness. Special attention should be paid to areas of the code that are exposed to this software flaw. By thinking like a hacker throughout the development process, you can avoid introducing OS command injection vulnerabilities in your own code.
Watch the on-demand webinar: Uncover What’s Inside the Mind of a Hacker
IBM X-Force Ethical Hacking Team Lead