Skip to content

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(/\A\d+((\+|-|\*|\/)\d+)*\z/)
            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));
    }
}