AI智能总结
演讲人张亚龙(ekkoo) About me 张亚龙id:ekkoo 钱塘征信安全攻防研究员 专注于JAVA/.NET应用安全、红队武器开发、云原生安全攻防 ●腾讯安全众测平台总榜Top 6●EDUSRC安全众测总榜Top1●阿里云先知众测梅花A●挖掘多个国内外大型通用系统0day累计赏金30万+●参加国家、省市护网攻击方多起,具有丰富的攻防对抗经验 开源项目:https://github.com/ekkoo-z技术分享:微信公众号「艾克Sec」 PART 01PART 02PART 03RASP定位与价值Java RASP核心实现机制RASP的攻击面与绕过实战PART 04未来的思考与展望 目录CONTENT PART 01 RASP定位与价值 实网攻防现状-AI赋能安全时代下的新挑战 对比AI时代前后,网络攻防手段、成本、自动化程度的巨大变革 传统防御手段为何难以应对0day? 依赖组件突发0day? WAF:依赖已知特征正则匹配需payload公开更新策略 EDR:聚焦主机进程等方面,不能深入程序内部,适用于后渗透阶段防御 RASP:填补应用层防御盲区的关键能力 RASP(Runtime Application Self-Protection,运行时应用自我保护) 深入应用运行时,基于真实执行上下文进行检测,能够精准感知代码级行为语义。 构建WAF(入口过滤)+RASP(应用内防护)+EDR(终端响应)立体化纵深防御体系 RASP解决方案 PART 02 Java RASP核心实现机制 RASP应用自保护整体架构示意图 基于RASP的应用实时防护与云端联动体系 RASP通过“字节码修改技术”对危险方法进行hook,结合策略下发、环境监测和强制中断等能力,在应用运行时实时阻断恶意行为 Java Agent与Instrumentation 目前主流的JavaRASP实现方案基于Instrumentation JVM提供的运行时插桩能力,主要通过JavaAgent技术,在类加载时动态修改字节码,注入安全检测逻辑,目前主流有两种实现方式: 1.Pre-main Agent●通过-javaagent:jar在JVM启动时加载●在类加载前(premain阶段)对目标类的字节码进行修改●需要重启但稳定 2.Attach Agent●利用pid动态attach到已运行的JVM●触发agentmain方法注册转换器进行插桩●不需要重启,对服务器性能消耗大 深入剖析RASP代码层实现原理 Step1:初始化 OpenRasp实现代码 ●通过-javaagent调用premain方法去初始化 通过retransform方法hook了许多危险类 ●SQL注入●反序列化●SSRF●命令执行●XXE●文件写入●Nday…… Step2:启动核心引擎 ●ModuleLoder加载核心防护引擎rasp-engine Step3:创建实例 ●调用initTransformer创建修改字节码的实例 ●调用transformClass对匹配的类进行字节码注入 深入剖析RASP代码层实现原理 OpenRASP检测策略差异 检测逻辑差异:doCheck只检测启用hook了的线程doCheckWithoutRequest都检测 PART 03 RASP的攻击面与绕过实战 SpEL注入:从表达式到任意代码执行 Spel表达式注入:应用程序直接将用户输入解析为Spring表达式语言执行导致攻击者可以通过表达式调用Java方法 Payload:T(java.lang.Runtime).getRuntime().exec('open-a calculator’) T(...)表示引用一个Java类的Class对象 T(java.lang.Runtime)等价于Java中的Runtime.class SPEL表达式注入场景下绕过RASP 直接使用攻击payload被绿色小恐龙Rasp拦截 ●当前线程堆栈中有用户请求●触发到恶意类ProcessImpl 利用线程转移规避RASP检测 仅拦截与用户请求线程上下文相关的操作 如果危险sink调用全部拦截 业务:掀桌子 线程转移绕过:将恶意操作从RASP监控的“请求线程”转移到未被监控的“非请求线程”中执行,从而规避基于线程上下文的安全检查 获取腾讯云RASP靶场所有依赖 需要在目标机器依赖中寻找一个冷门没被黑名单起新线程的方法 如何绕过rasp获取机器依赖? Spring框架可以使用getCurrentWebApplicationContext方法获取WebApplicationContext实例 包含了:所有注册过的Bean数据源、事务管理器、配置属性完整的依赖注入图谱 尝试寻找绕过方法 需要寻找一个冷门没被黑名单起新线程的方法 org.apache.catalina.core.StandardThreadExecutor#execute 该方法将Runnable任务提交到Tomcat内置的线程池中进行异步执行,会触发新线程创建 需要满足条件:●传入一个实现了Runnable接口的对象 ●这个对象必须有恶意的方法可以被利用 尝试寻找绕过方法 进而寻找一个实现Runnable接口并且能触发恶意方法的类 都可以反射调用任意方法 使用Agent工具在大量的依赖中快速检索到两个危险类 ScheduledMethodRunnable已经被公开过了,直接看MethodInvokingRunnable org.springframework.scheduling.support.ScheduledMethodRunnable org.springframework.scheduling.support.MethodInvokingRunnable MethodInvokingRunnable:反射调用的“万能钥匙” 足够暴力!设置父类属性可直接invoke调用任意对象的任意方法 MethodInvokingRunnable:反射调用的“万能钥匙” Spel表达式支持多行以及变量赋值,配合新起线程类可以成功执行命令 在堆栈中可以看到已经没有用户请求的特征了但在RASP防护下依旧被拦截 仍被拦截:利用产品检测逻辑差异绕过 doCheck只检测启用hook了的线程,而doCheckWithoutRequest都检测 命令执行拦截hook使用doCheckWithoutRequest因此反射调用命令执行依旧拦截 文件写入hook使用doCheck,尝试进行文件写入 成功绕过:文件写入 通过创建新线程成功绕过OpenRASPhook写入jspx文件 不存在用户上下文交互,也不存在反射被当成业务代码直接执行 腾讯云Rasp会禁止new常用的文件写入类需进一步查找未被黑名单的类进行绕过 单一手段往往不足 方法重复 黑名单局限:总有未覆盖的类 未被hook的点+腾讯云raps小tips绕过 ●寻找未被hook的危险方法org.apache.commons.collections.ExtendedProperties#save 传入OutputStream对象以及写入内容 内部调用PrintWriter进行文件写入绕过黑名单检测 黑名单局限:总有未覆盖的类 寻找未被黑名单的危险类org.apache.commons.configuration.DefaultFileSystem#getOutputStream 可将传入File对象返回OutputStream对象 javax.swing.filechooser.FileSystemView#createFileObject 可传入字符串返回File对象 黑名单局限:总有未覆盖的类 完整路径 需要调用addProperty方法存储属性才能正常写入通过注释符绕过 条件竞争绕过堆栈上下文检测 腾讯云RaspTips:猜测在线程上下文中有个强制中断机制 已经创建对象实例,后续调用危险方法被动态拦截 可尝试条件竞争绕过! 条件竞争绕过上下文检测 未被hook的点+tips绕过 创建黑名单类对象全部拦截,条件竞争并没有用 条件竞争绕过上下文检测 未被hook的点+tips绕过 未被黑名单的类成功创建实例但最终写入文件时堆栈中有用户上下文也有危险sink会被直接拦截 成功获取flag 条件竞争写入文件访问jsp执行命令,无用户上下文也不存在反射调用成功获取flag 其他方法 2、产品特性针对性利用: 1、JNI(Java Native Interface)绕过:将恶意操作从Java层转移到Native层执行,从规避基于Java字节码插桩的RASP监控。 不同RASP产品在设计理念、防护策略和实现机制上存在差异通过深入分析特定产品的特性可以发现其防护的薄弱环节, 这类技术的有效性往往依赖于产品的开源特性和源码可获取性 使用System.loadLibrary加载so或dll文件后执行方法 利用条件较苛刻:●需要上传恶意dll和so●Java任意代码执行常用于文件上传场景 PART 04 未来的思考与展望 RASP攻防的未来思考 对于实战攻防当中红蓝两方RASP平衡的难题 除了本篇提到的针对基于Java语言层的RASP绕过方法,新一代RASP已开始采用ASM/JVMTI/JNI等技术,同时工作在Java层和JVM层:Java层提供丰富的应用日志,而核心拦截处理放在JVM空间,使得绕过变得更加困难。 THANKS 演讲人张亚龙(ekkoo)