Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Parasoft Jtest 2022.2

Code injection is caused as a result of can occur when untrusted input being is injected into dynamically constructed code. One obvious source of potential vulnerabilities is the use of JavaScript from Java code. The  The javax.script package provides utilities to use various scripting engines from consists of interfaces and classes that define Java scripting engines and a framework for the use of those interfaces and classes in Java code. Misuse of these utilities the javax.script API permits an attacker to execute arbitrary code on the target system. Such errors are dangerous because violations of secure coding practices in dynamically generated code cannot be detected in advance through static analysis

This guideline is a specific instance of IDS00-J. Prevent SQL injection.

Noncompliant Code Example

This noncompliant code example incorporates untrusted user input in into a javascript JavaScript statement that is responsible for printing the input:

Code Block
bgColor#FFCCCC
private static void evalScript(String firstName) throws ScriptException {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  engine.eval("print('"+ firstName + "')");	
}

An attacker can enter a specially crafted arguments argument in an attempt to inject malicious javascript. The firstName string contains javascript JavaScript. This example shows a malicious string that contains JavaScript code that can create a file or overwrite an existing file on the system running the vulnerable Java codea vulnerable system.

Code Block
bgColorffffcc
language#FFCCCCjavascript

// Windows based target's file path is being used
String firstName = "dummy\'); 
var bw = new JavaImporter(java.io.BufferedWriter); 
                    var fw = new JavaImporter(java.io.FileWriter); 
                    with(fw) with(bw) { 
                    bwr = new BufferedWriter(new FileWriter(\"c://somepath//somefile.txtconfig.cfg\"));
                    bwr.write(\"some text\"); bwr.close(); 
} 
// "; 
	  
evalScript(firstName);

The script in this example prints "dummy" and then writes "some text" to a configuration file called config.cfg.  An actual exploit can execute arbitrary code.

Compliant Solution (Whitelisting)

The best defense against code injection vulnerabilities is to prevent the inclusion of executable user input in code. User input used in dynamic code must be sanitized, for example, to ensure that it contains only valid, whitelisted characters. Sanitization is best performed immediately after the data has been input, using methods from the data abstraction used to store and process the data. Refer to IDS00-J. Sanitize untrusted data passed across a trust boundary for more details. If special characters must be permitted in the name, they must be normalized before comparison with their equivalent forms for the purpose of input validation. This compliant solution uses whitelisting to prevent unsanitized input from being interpreted by the scripting engine.

Code Block
bgColor#ccccff
private static void evalScript(String firstName) throws ScriptException {
  // Allow only alphanumeric and underscore chars in firstName
  // (modify if firstName may also include special characters)
  if (!firstName.matches("[\\w]*")) { 
    // String does not match whitelisted characters
    throw new IllegalArgumentException();
  } 

  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("javascript");
  engine.eval("print('"+ firstName + "')");	
}

Compliant Solution

...

The best defense against code injection vulnerabilities is to avoid including executable user input in code. When dynamic code requires user input, that input must be sanitized. For example, a top-level method could ensure that the string firstName contains only valid, white-listed characters. Refer to the guideline IDS01-J. Sanitize data passed across a trust boundary for more details. If special characters are allowed in the name, they must be escaped before comparing with their equivalent forms.

(Secure Sandbox)

An alternative approach In addition, a complementary policy is to create a secure sandbox using a security manager . (See guideline ENV02see SEC54-J. Create a secure sandbox using a Security Manager.) This approach is akin to the one discussed in the first compliant solution of guideline VOID IDS10-J. Prevent XML external entity attacks. security manager.)  The application should not allow prevent the script to execute from executing arbitrary commands including, for example, such as querying the local file system. The two-argument form of of doPrivileged() can  can be used to lower privileges when the application must operate with higher privileges, but the scripting engine must not. The The RestrictedAccessControlContext strips  reduces the permissions granted in the default policy file by reducing the permissions granted to those of the newly created protection domain. The effective permissions are the intersection of the permissions of the newly created protection domain and the system wide systemwide security policy. Refer to the guideline SEC00to SEC50-J. Avoid granting excess privileges for  for more details on the two-argument form of doPrivileged().

This compliant solution illustrates the use of an AccessControlContext in the two-argument form of doPrivileged().

Code Block
bgColor#ccccff

// First sanitize firstName (modify if the name may include special characters)

if(!firstName.matches("[\\w]*")) { // String does not match white-listed characters
  throw new IllegalArgumentException();
} 

class ACC {
  private static class RestrictedAccessControlContext {
    private static final AccessControlContext INSTANCE;
  
    static {
      INSTANCE = new AccessControlContext(
                   new ProtectionDomain[] { 
                     new ProtectionDomain(null, null) // No permissions
                   });
    }
  }
  
  private static void evalScript(final String firstName)
      throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    final ScriptEngine engine = manager.getEngineByName("javascript");
    // Restrict permission using the two-argument form of doPrivileged()
    try {
      AccessController.doPrivileged(
        new PrivilegedExceptionActionPrivilegedExceptionAction<Object>() {
                        
          public Object run() throws ScriptException {
            engine.eval("print('" + firstName + "')");		
            return null;
          }
      	
  }, 
        // From nested class
        RestrictedAccessControlContext.INSTANCE);
                                                                    
    } catch (PrivilegedActionException pae) {
    	
  // Handle error
}    }
   

...

}
}

This approach can be combined with whitelisting for additional security.

Applicability

Failure to prevent code injection can result in the execution of arbitrary code.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

IDS12-J

high

likely

medium

P18

L1

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Bibliography

Wiki Markup
\[[API 2006|AA. Bibliography#API 06]\] Package {{javax.script}}
\[[OWASP 2008|AA. Bibliography#OWASP 08]\] [Code injection in Java|http://www.owasp.org/index.php/Code_injection_in_Java]

Automated Detection

ToolVersionCheckerDescription
The Checker Framework

Include Page
The Checker Framework_V
The Checker Framework_V

Tainting CheckerTrust and security errors (see Chapter 8)
Parasoft Jtest
Include Page
Parasoft_V
Parasoft_V
CERT.IDS52.TDCODEValidate potentially tainted data before it is used in methods that generate code

Bibliography


...

Image Added Image Added Image AddedIDS51-J. Prevent LDAP injection      Image Removed      IDS13-J. Account for supplementary and combining characters in globalized code