不当的代码生成控制¶
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
如果应用程序动态编译并运行从用户输入构造的源代码,则恶意用户可能能够运行任意代码。
建议¶
良好的做法是不生成、编译和运行从不受信任的用户输入构造的源代码。如果必须使用用户输入动态生成代码,则应验证用户输入,以防止任意代码出现在输入中。例如,可以使用白名单来确保输入限制在可接受的值范围内。
示例¶
在以下示例中,HttpHandler 接受远程用户输入,该输入是用于计算税款的 C# 源代码。它会编译并运行此代码,并返回输出。但是,用户提供的源代码完全未经验证,因此允许执行任意代码。
如果可能,应完全删除动态编译,并将其替换为一组固定的税款计算算法。如果这还不够强大,可以为安全、受限的语言提供解释器。
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);
}
}