Improper control of generation of code¶
ID: cs/code-injection Kind: path-problem Security severity: 9.3 Severity: error Precision: high Tags: - security - external/cwe/cwe-094 - external/cwe/cwe-095 - external/cwe/cwe-096 Query suites: - csharp-code-scanning.qls - csharp-security-extended.qls - csharp-security-and-quality.qls
Click to see the query in the CodeQL repository
If the application dynamically compiles and runs source code constructed from user input, a malicious user may be able to run arbitrary code.
Recommendation¶
It is good practice not to generate, compile and run source code constructed from untrusted user input. If code must be dynamically generated using user input, the user input should be validated to prevent arbitrary code from appearing in the input. For example, a whitelist may be used to ensure that the input is limited to an acceptable range of values.
Example¶
In the following example, the HttpHandler accepts remote user input which is C# source code for calculating tax. It compiles and runs this code, returning the output. However, the user provided source code is entirely unvalidated, and therefore allows arbitrary code execution.
If possible, the dynamic compilation should be removed all together, and replaced with a fixed set of tax calculation algorithms. If this is not sufficiently powerful, an interpreter could be provided for a safe, restricted language.
using Microsoft.CSharp; using System; using System.CodeDom.Compiler; using System.Reflection; using System.Web; public class CodeInjectionHandler : IHttpHandler { public void ProcessRequest(HttpContext ctx) { // Code for calculating tax is provided as unvalidated user input string taxFormula = ctx.Request.QueryString["tax_formula"]; // Used to create C# StringBuilder sourceCode = new StringBuilder(""); sourceCode.Append("public class TaxCalc {\n"); sourceCode.Append("\tpublic int CalculateTax(int value){\n"); sourceCode.Append("\t\treturn " + taxFormula + "; \n"); sourceCode.Append("\t}\n"); sourceCode.Append("}\n"); // BAD: This compiles the sourceCode, containing unvalidated user input CSharpCodeProvider c = new CSharpCodeProvider(); ICodeCompiler icc = c.CreateCompiler(); CompilerParameters cp = new CompilerParameters(); CompilerResults cr = icc.CompileAssemblyFromSource(cp, sourceCode.ToString()); // Compiled input is loaded, and an instance of the class is constructed System.Reflection.Assembly a = cr.CompiledAssembly; object taxCalc = a.CreateInstance("TaxCalc"); // Unsafe code is executed Type taxCalcType = o.GetType(); MethodInfo mi = type.GetMethod("CalculateTax"); int value = int.Parse(ctx.Request.QueryString["value"]); int s = (int)mi.Invoke(o, new object[] { value }); // Result is returned to the user ctx.Response.Write("Tax value is: " + s); } }
References¶
Wikipedia: Code Injection.
OWASP: Code Injection.
Common Weakness Enumeration: CWE-94.
Common Weakness Enumeration: CWE-95.
Common Weakness Enumeration: CWE-96.