0x01 命令注入
在开发过程中,开发人员可能需要对系统文件进行移动、删除或者执行一些系统命令,这时如果执行的命令用户可控,就会导致命令执行漏洞。
1、示例
当命令可控时,就可能会导致命令注入,例如以下代码:
String cmd = request.getParameter("cmd");
Runtime.getRuntime().exec(cmd);
这种漏洞原理很简单,主要就是找到执行系统命令的函数,看命令是否可控。
java 程序中执行系统命令的函数如下:
Runtime.exec
Process
ProcessBuilder.start
GroovyShell.evaluate
...
2、命令注入的限制
对于系统命令,可以使用连接符来执行多条语句,常见连接符及含义如下:
; 多个命令顺序执行,命令之间无任何逻辑关系
| 前面命令输出结果作为后面命令的输入内容
|| 逻辑或,当前面命令执行失败后,后面命令才会执行,否则后面命令不执行
& 前面命令执行后继续执行后面命令
&& 逻辑与,当前面命令执行成功后,后面命令才会执行,否则后面命令不执行
对于 Java 环境中的命令注入,连接符的使用存在一些限制,例如以下代码:
Runtime.getRuntime().exec("ping " + url);
这里因为 URL 可控,因此当我们输入 127.0.0.1&ipconfig 时,拼接出来的系统命令就是 ping 127.0.0.1&ipconfig,该命令在系统终端下是能正常运行的,但是在 Java 环境下就会运行失败,这里因为 Java 在程序处理的过程中,会将 127.0.0.1&ipconfig 当做一个完整的字符串而非两条命令,因此上面的代码不存在命令注入。
0x02 代码注入
1、介绍
代码注入因为是直接注入一段代码,因此要比命令注入更加灵活,危害性也更大。
这里以 Apache Commons collections 组件为例。
Apache Commons collections 组件 3.1 版本有一段利用反射来完成特定功能的代码,控制相关参数后,就可以进行代码注入。
这里攻击者可以利用反序列化的方式控制相关参数,完成注入代码,达到执行任意代码的效果。
与命令注入相比,代码注入更具有灵活性,例如在 Apache Commons collections 反序列化漏洞中直接使用 Runtime.getRuntime().exec() 执行系统命令是无回显的,但如果通过 URLLoader 远程加载类文件以及异常处理机制就可以构造出回显的利用方式。
这里就以 Apache Commons collections 反序列化漏洞为例,体验一下代码注入,因为现阶段个人水平有限,这里还不能对 Apache Commons collections 反序列化漏洞的原理进行深入分析,等后面学习到相关内容的时候不出意外应该还会碰到这个漏洞,那个时候再好好分析分析这个漏洞。
2、Apache Commons collections 反序列化漏洞复现
环境搭建
该漏洞影响了 3.1 及以下的版本,这里以 3.1 版本为例,首先下载 commons-collections-3.1.zip 文件,下载地址:https://archive.apache.org/dist/commons/collections/binaries/commons-collections-3.1.zip
解压 commons-collections-3.1.zip 可以得到 commons-collections-3.1.jar 文件,接下来打开 intelliJ IDEA,创建一个普通的 Java 项目,然后选择「文件 --> 项目结构 --> 库 --> + --> Java」,添加 commons-collections-3.1.jar 包,我使用的 jdk 版本为 1.8.0_191
接下来在「src --> com --> commons」目录下创建 ApacheCommonsCollectionsDemo.java 文件(右击 com.commons 软件包选择:新建 --> Java 类文件)
无回显利用
在 ApacheCommonsCollectionsDemo.java 文件下写入以下代码
package com.commons;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.TransformedMap;
public class ApacheCommonsCollectionsDemo {
public static void main(String[] args