启动mysql,然后创建数据库。
然后导入.sql文件。
修改数据库名和用户名。
全局搜素 ${ ,查看那些地方调用了这些参数,主要是查看${} 拼接 SQL 语句的地方。
进入src/main/resources/mapper/NewBeeMallGoodsMapper.xml 第 70 行
首发分析 NewBeeMallGoodsMapper.xml,该部分中 goodsName 参数存在 SQL 注入,使用了直接拼接的方式向数据库进行查询。
进入src/main/java/ltd/newbee/mall/dao/NewBeeMallGoodsMapper.java 源码。
逆向追踪findNewBeeMallGoodsList 方法
进入src/main/java/ltd/newbee/mall/service/impl/NewBeeMallGoodsServiceImpl.java ,在
getNewBeeMallGoodsPage 方法中使用了 goodsMapper.findNewBeeMallGoodsList 方法
追踪查看谁调用了getNewBeeMallGoodsPage 方法,
定位到位于src/main/java/ltd/newbee/mall/controller/admin/NewBeeMallGoodsController.java 。
点击 133 行中 params,可以看到该参数来自第 129 行,是一个 Map 对象,它需要从请求中获取参数。
进入商品管理。使用添加商品。
然后使用burp抓包。
然后在god参数后面添加分号,出现报错注入。
也可以使用sqlmap来进行验证。
进入src/main/java/ltd/newbee/mall/interceptor/AdminLoginInterceptor.java
首先,关键点是第 23 行,使用了 request.getRequestURI() 方法获取路径。 getRequestURI 方法返回的路径是未经过服务器端处理的原始路径,可能包含特殊字符或路径跳转,从而绕过服务器端的安全控制。接着,第 24 行使用了 uri.startsWith("/admin") 判断 Uri 路径中是否以 /admin 开头,以及获取并判断Session 中的 loginUser 属性是否为 null,两个条件 && 在一起结果为 True 的话进入条件代码。
登陆后台寻找一个后台接口。
删除 Cookie 后,也就是没有访问权限了。
发送数据包,显示需要跳转到登录页面
${ 关键字进行全局搜索 ${
定位到源码:src/main/java/ltd/newbee/mall/dao/NewBeeMallGoodsMapper.java
继续向上追踪查看谁调用 searchNewBeeMallGoods 方法,最终跳转到
GoodsController,位于src/main/java/ltd/newbee/mall/controller/mall/GoodsController.java
漏洞点在第 57 行,传入了 pageUtil 参数,而该参数同样通过 PageQueryUtil 类创建一个 pageUtil 对
象,传入 params 作为参数,以及 params 同样是个 Map 对象。未对其进行过滤处理。
进入漏洞接口处,然后使用burp进行抓包,然后在参数处输入单引号。
发现存在报错注入。
可以使用sqlmap进行验证。
进入前端搜索框界面,然后输入xss的paylaod,进行黑盒测试。
没有实现弹框,然后去xss当中去看看。
去源码中看看,发现存在转义。
thymeleaf模版在对th:text标签进行渲染的时候,默认对特殊字符进行了转义,
接着进入/src/main/resources/templates/mall/search.html:33
找thymeleaf未作转义的输出,th:utext不会将字符转义
发现以下模版中存在th:utext,所以这两个功能点存在XSS。其中第二个,detail.html因为显示的是商品信息,商品信息使用富文本编辑器,不能简单的转义处理,需要考虑正常的html标签传输,所以作者在这里使用th:utext来显示商品详细。
进入商品信息,添加xss的payload
成功实现弹框。
进入订单管理,然后添加payload
成功实现弹框。
进入新品上线配置模块
添加xss的payload
成功实现弹框。
进入/src/main/java/ltd/newbee/mall/config/NeeBeeMallWebMvcConfigurer.java中,发现针对url路径设置了不同的interceptor。addPathPatterns表示其中的路径会经过设置的拦截器,excludePathPatterns则不过该拦截器。其中两个星*表示匹配任意字符。如果出现一个则表示匹配单个路径
对请求的路由进行判断是应该使用 getServletPath() 来获取最后真正分发到路由地方的 path
getRequestURI() 只是获取了请求的 URI。
使用了 getRequestURI() 来获取URI来判断URI是否以 /admin 开头,如果是 /admin 开头则校验 session,不是则不用校验。
进入dashboard模块
然后输入//admin 或 /index/..;/admin也可以成功访问到页面。
成功绕过了目录访问字符限制。
定位到源码:ltd/newbee/mall/controller/mall/PersonalController.java:114
接着看 updateUserInfo() 的实现,
发现这里从数据库查找用户并未用到 session ,而是直接以传递过来的 userId 为参数来查找并修改数据的,所以这里存在水平越权漏洞,修改 userId 便可修改其他用户的信息。
注册一个用户,然后查看个人信息。
使用burp抓包,用户 userId 为 9
然后修改userid,成功修改其它用户信息。
进入查询订单的源码:td/newbee/mall/controller/mall/OrderController.java:36
跟进getOrderDetailByOrderNo() 函数
这里用户 userId 为9的用户下的单
替换为其它用户cookie,也可以看到订单信息。
我们使用添加购物车功能为例,请求内容为下,没有任何token值来进行校验。
由于是json格式的请求,不能直接使用burp Generate CSRF PoC,因为burp生成的PoC无法伪造Content-Type。burp生成的CSRF PoC请求内容如下,可以看到Content-Type: text/plain,并且post数据多出一个等号。
未授权访问商品 http://localhost:8089/index/..;/admin/goods/edit/10896
然后生成csrf的poc。进行抓包。
然后成功写入xss的payload。
成功添加商品到购物车当中。
下订单但未支付时,访问/orders/{orderNo}/finish可直接完成交易。
从代码中发现直接调用newBeeMallOrderService.finishOrder(orderNo, user.getUserId()),对于该订单是否支付,是否出库等过程都没有校验。
因为代码使用的是@PutMapping,使用PUT方法访问,其他请求方法不会被执行。
添加一件物品到购物车,然后提交订单。
然后点击去支付,选择支付宝支付,一系列流程下来可以购买商品。
我们进入商品后台,订单一开始是未支付。
我们使用put方式去请求。
成功支付商品。
REF:
https://cloud.tencent.com/developer/article/2169674
https://s31k31.github.io/2020/04/25/JavaSpringBootCodeAudit-1-Preparation/