dynamic-code-injection¶
Dynamically evaluating code from raw strings at runtime is a powerful feature available in many programming languages. It is critical to avoid passing arbitrary user data into such functions as it would enable an attacker to take full control over the execution of the program. If you need to provide some degree of scriptability to your users, prefer creating a Domain-Specific Language (DSL) by parsing known safe commands that would allow you to keep control over the execution. In cases where you wish to directly leverage the language runtime, make sure to sanitize the user input so that it has a predictible, limited effect.
Examples¶
Insecure Example
from flask import request
@app.route('/')
def index():
module = request.args.get("module") # User input
# eval() is also equally dangerous
exec("import urllib%s as urllib" % module) # Allows the user to execute arbitrary Python code
class SomeController < ApplicationController
def index
user_math_formula = params[:math_formula] # # Such as "23+55-66" or "system('id')"
puts eval(user_math_formula) # Could take over the execution of the program
end
end
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
userInput = args[0] // Arbitrary user input
// Such as:
/*
importPackage(java.lang.runtime);
java.lang.runtime.Runtime.exec("id");
*/
System.out.println(engine.eval(userInput));
}
}
Secure Example
from flask import request
@app.route('/')
def index():
module = request.args.get("module") # User input
exec("import urllib%d as urllib" % int(module)) # Still dangerous, but limits the user's impact to the execution of code
class SomeController < ApplicationController
def index
user_math_formula = params[:math_formula] # Such as "23+55-66"
if user_math_formula.match(/\d+((\+|-|\*|\/)\d+)*/)
puts eval(user_math_formula) # Limits the dynamic evaluation to predictible, safe behaviors
else
puts "Unauthorized input"
end
end
end
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
userInput = args[0] // Arbitrary user input - Such as "23+55-66"
if (!userInput.matches("\d+((\+|-|\*|\/)\d+)*")) {
throw new IllegalArgumentException();
}
System.out.println(engine.eval(userInput));
}
}