How To Identify and Prevent Query and Command Injections (Part 1)

security shield

 

security shield

Query and command injections are some of the most devastating classes of vulnerabilities in existence. This series of blog posts will teach you how to identify and prevent this vulnerability from occurring.

What is command injection?

Similar to SQL injection, the root cause of command injection is unvalidated data. Command injection can occur when unsanitized, user-controlled input is passed as input to execution calls. If a developer is not careful, dynamically built commands can be used by an attacker to perform arbitrary execution on the underlying operating system. This is accomplished by appending additional commands to the intended command string.

As an example, let’s examine a small snippet of vulnerable PHP code that was identified during an actual assessment. To protect the innocent and ourselves the code has been anonymized.

Vulnerable PHP code

[code]
function getReport($jsonArgs){
$cmd = ‘/usr/local/bin/report.sh -a ‘ . $jsonArgs ->reportId;
output = shell_exec($cmd);

}
[/code]

Tracing back through the code, and as you can probably already guess, the jsonArgs object is passed from an untrusted source that can be influenced by the user. Since no attempt has been made to sanitize the serialized data by the time getReport() is called, an attacker can control the argument of shell_exec() by manipulating the json->reportId value. As a simple demonstration, consider the following request:

HTTP Request

[code]
X-REquested-With: XMLHttpRequest
Referer: http://www.domain.com
Content-Length: 159
PHPSESSID:6a33e696d72fd447caa0df9e229aad3
Pragma: no-cache
Cache-Control: no-cache

{“action”:”acmeDirect”,”method”:”getReport”,”data”:[“397MPIS10COSHTUBJGBG4B8365G9GJ9475Y4F21L”,{“reportId”:”test; sleep 25; echo”}],”type”:”rpc”,”tid”:239}
[/code]

When the application executes the command via a shell, it will also run the appended commands injected via the input parameter. While this example is benign and will simply cause the request to wait 25 seconds before returning, much more sinister requests can be injected.

Example command executes via a shell

[code]
/usr/local/bin/stats.sh -a test; sleep 25; echo
[/code]

Preventing Command Injection

Similar to SQL injection, the starting point begins with validating user input. In practice, input should be validated as close to the external interface as possible, but for simplicity’s sake, we show our validation process within the getReport() function. Implementation details will vary depending on the language. Regarding the particulars of this PHP example, an easy fix would first ensure reportId is an integer and only an integer via the is_numeric() function. We can then use escapeshellarg() function to wrap the input to ensure its passed as a single string to the command.

Easy Fix Example PHP

[code]
function getReport($jsonArgs) {
if (is_numeric($jsonArgs ->reportId) && $jsonArgs ->reportId >= 1) {
$cmd = ‘/usr/local/bin/report.sh -a ‘ . escapeshellarg($jsonArgs ->reportId);
output = shell_exec($cmd);
} else {
// error
}

}
[/code]

But wait… Consider this

While the simple fix is secure, it doesn’t consider underlying vulnerabilities that may exist within the PHP language itself. A more secure solution would be to avoid the use of a shell interpreter within PHP by using pcntl_fork and pcntl_exec, but many developers would tell you that those functions are not easy to work with. That is why frameworks that default to the more secure design pattern of avoiding the shell interpreter all together are recommended.

Python is one such language where developers are directed towards using modules that will not invoke the shell unless forced too. This creates a “secure by default” environment where the entire class of vulnerabilities may not exist unless the developer goes out of their way to use a less secure design.

About the Authors

Nathan Sportsman

Nathan Sportsman

As the Founder and CEO of Praetorian, Nathan is responsible for championing the vision, maintaining the culture, and setting the direction of the company. Prior to bringing in professional management to help run the company, Nathan managed the day-to-day operations of the firm from its 2010 beginnings as a bootstrapped start-up to its current YoY hyper-growth. Since Praetorian’s founding, Nathan has successfully instilled a “customer first” mentality that has become part of the DNA of the company, which has led to unprecedented customer satisfaction reviews as reflected in a historical net promoter score of 92%. This reputation for delivering value to the customer has resulted in a three-year growth rate of 214%. Under Nathan’s leadership, the company has earned national recognition on the Inc. 5000 list 8 times in a row, the Inc Best Work Places, the Cybersecurity 500, CIO Top 20, and locally on Austin’s “Fastest 50” growing firms.

Catch the Latest

Catch our latest exploits, news, articles, and events.

Ready to Discuss Your Next Continuous Threat Exposure Management Initiative?

Praetorian’s Offense Security Experts are Ready to Answer Your Questions

0 Shares
Copy link