ewbee-mall是一套电商系统代码审计

1 sql注入1

1.1 sql注入1代码审计

在对该项目进行简单梳理时,发现该项目使用了 Mybatis 持久层框架,可以简单理解成操作数据的第三方依赖

因此,我们可以在项目中全局搜素关键字 ${ ,查看是否使用了存在风险的拼接方式,共发现四处使用${} 拼接 SQL 语句的地方,如下所示:

我们鼠标单击进入第一个漏洞点,该漏洞位于

src/main/resources/mapper/NewBeeMallGoodsMapper.xml 第 70 行,如下图所示:

下面我们开始分析代码,并逆向追踪触发该漏洞点的功能。

①、第一步:分析 NewBeeMallGoodsMapper.xml 映射文件第 64 至 71 行,该部分中 goodsName 参数存在 SQL 注入,使用了直接拼接 SQL 语句的方式向数据库进行查询。具体代码分析如下,及如下图所示:

<if test="goodsName!=null and goodsName!=''"> :这是一个条件判断,它检查变量

goodsName 是否不为 null 且不为空字符串。如果条件为真,下面的 SQL 语句块将会被包含在生成的查询语句中;否则,该 SQL 语句块将被忽略。

and goods_name like CONCAT('%','${goodsName}','%') :这是在生成的 SQL 查询语句中的一个条件部分。它使用了 like 关键字来进行模糊匹配,查找包含特定字符串的记录。 CONCAT()函数是用于连接字符串的。在这里,它连接了三个部分: '%' 是一个百分号字符,用于匹配任意字符; ${goodsName} 是一个占位符,它会被实际的 goodsName 变量的值替换;再次使用 '%' 进行匹配结尾的任意字符。这样的组合就可以实现在 goods_name 列中模糊匹配指定的字符串。

第二步:我们逆向追踪到映射接口,如果安装了类似 Free Mybatis plugin 的插件,我们只需点击左侧绿色箭头即可跳转过去(或者全局搜索 id findNewBeeMallGoodsList 也是可以的),

NewBeeMallGoodsMapper 映射接口代码位于

src/main/java/ltd/newbee/mall/dao/NewBeeMallGoodsMapper.java ,如下图所示

第三步:继续逆向追踪,查看谁调用了 NewBeeMallGoodsMapper.java 接口中的

findNewBeeMallGoodsList 方法,我们只需键盘按住 Ctrl + 鼠标左键点击该方法即可看到调用关系,即

NewBeeMallGoodsServiceImpl.java 中的 getNewBeeMallGoodsPage 方法 ,如下图所示:

第四步:进入 NewBeeMallGoodsServiceImpl.java,位于src/main/java/ltd/newbee/mall/service/impl/NewBeeMallGoodsServiceImpl.java ,在getNewBeeMallGoodsPage 方法中使用了 goodsMapper.findNewBeeMallGoodsList 方法,即第 27行,没有什么其他额外需要注意的操作。如下图所示:

第五步:继续逆向追踪,查看谁调用了 getNewBeeMallGoodsPage 方法,还是只需键盘按住 Ctrl +鼠标左键点击该方法即可看到调用关系,直接跳到了 NewBeeMallGoodsController,位于src/main/java/ltd/newbee/mall/controller/admin/NewBeeMallGoodsController.java ,在第137 行使用了 getNewBeeMallGoodsPage 方法,如下图所示:

第六步:分析 NewBeeMallGoodsController 中 list 方法代码,即第 127 到 135 行。首先,点击第 134 行中 pageUtil,该参数来自第 133 行,通过 PageQueryUtil 类创建一个 pageUtil 对象,传入 params 作为参数。PageQueryUtil 是作者自定义的工具类,是用于处理分页相关的操作。然后,点击 133 行中 params,可以看到该参数来自第 129 行,是一个 Map 对象,可以简单理解为它需要从请求中获取参数。

最后,整理代码信息可以的到接口路径为 /goods/list ,请求为 GET 方法,是个列表功能,根据代码路径来看应该是后台功能,这么看来我们找到了漏洞前端功能点。如下图所示:

1.2 漏洞验证

根据代码审计拼凑出来的信息,我们登录进后台管理,并且使用 BurpSuite 进行抓包。

最终在商品管理功能处的换页面找到了该接口,如下图所示:

但是发现没有 goodsName 参数,我们给它手动加上去并尝试使用单引号(')触发报错,如下图所示:

最后,交给 SQLmap 了,验证结果如下图所示:

2 sql注入2

2.1 sql注入方式2代码审计

我们就选择 NewBeeMallGoodsMapper.xml 第 94 行这个 keyword 吧,先对映射文件的漏洞点进行简单分析。

和上面那个 SQL 注入漏洞一样,使用了 like CONCAT('%','${keyword}','%') 方式拼接了 SQL 语句进行了模糊查询,代码上面也没什么其他额外需要注意的。

第一步:逆向追踪到 NewBeeMallGoodsMapper.java 映射接口,位于src/main/java/ltd/newbee/mall/dao/NewBeeMallGoodsMapper.java ,点击第 31 行处findNewBeeMallGoodsListBySearch 方法逆向查看调用关系,如下图所示:

第二步:进入到 NewBeeMallGoodsServiceImpl,漏洞点位于第 73 行,由于是

searchNewBeeMallGoods 这个方法下第一行代码,代码通常是逐行按顺序执行的,下面代码就没什么

可分析的了,继续向上追踪查看谁嗲用了 searchNewBeeMallGoods 方法,最终跳转到GoodsController,位于

src/main/java/ltd/newbee/mall/controller/mall/GoodsController.java ,如下图所示:

漏洞点在第 57 行,传入了 pageUtil 参数,而该参数同样通过 PageQueryUtil 类创建一个 pageUtil 对象,传入 params 作为参数,以及 params 同样是个 Map 对象。

主要分析第 31 至 54 行,查看对 params 做了哪些操作,是否有 SQL 注入防范过滤代码,但分析下来发现,并没有任何防范代码。

主要是使用了 params.containsKey 方法检测是否包含指定的键(key),如果包含一些特定的值,比如goodsCategoryId,就做一些特定处理。以及对 keyword 做了过滤,去掉了空格。

最后,整理代码信息可以的到接口路径为 /search 或 /search.html ,请求为 GET 方法,应该是个搜索功能,根据代码路径来看应该是前台功能,这么看来我们找到了漏洞前端功能点。如下图所示:

2.2 sql漏洞验证

根据代码审计拼凑出来的信息,我们访问前台购物页面,在搜索框处发现了漏洞接口,如下图所示:

还是交给 SQLmap 了,验证结果如下图所示:

3 xss

3.1 xss代码审计

首先黑盒测试下

搜索框这里并没有XSS,到源码中去看看

可以看到后端并没有对传入的 keyword 做任何处理。但确实是没有XSS。同时审计其他地方也未发现有任何的过滤或替换。但这里没有XSS成功,原因是项目使用了 thymeleaf 模板来渲染,模板自带有字符转义的功能。

这里对搜索的字符串显示使用了 th:text

输出的是转义后的字符串。想要得到未经过模板转义后的字符串通过 th:utext 来实现,全局搜索下找到了这两处

3.2xss漏洞验证

第一处在 detail.html 中。是显示商品的介绍。

这里只能通过admin面板的商品介绍处修改

抓包修改标签

前台该商品的介绍成功触发XSS

4 后台权限绕过漏洞

4.1 后台权限绕过漏洞审计

发现后台系统身份验证拦截器 AdminLoginInterceptor.java 存在权限绕过漏洞。

漏洞代码位于: src/main/java/ltd/newbee/mall/interceptor/AdminLoginInterceptor.java ,第 21 ~ 32 行,代码如下图所示:

漏洞主要发生于第 23 行和第 24 行,下面我们分析下漏洞成因。

首先,关键点是第 23 行,使用了 request.getRequestURI() 方法获取路径。如果使用该方法获取的路径进行权限判断是极易出现权限绕过漏洞的。

简单来说, getRequestURI 方法返回的路径是未经过服务器端处理的原始路径,可能包含特殊字符或路径跳转,从而绕过服务器端的安全控制。

其次,第 24 行使用了 uri.startsWith("/admin") 判断 Uri 路径中是否以 /admin 开头,以及获取并判断Session 中的 loginUser 属性是否为 null,两个条件 && 在一起结果为 True 的话进入条件代码,提示需要登录并跳转到后台登录页面中。

既然这样,我们知道 a && b 需要两者都为 True 整体则为 True 才会进入条件判断代码中,如果另其中一个条件为 False 则整体就为 False,就不会进入条件判断中去了。

这两个条件中,Session 部分我们是没办法操纵的。但uri.startsWith("/admin") 这个条件我们可以搞点

小破坏,前面提到了 uri 是使用的 getRequestURI 方法获取的原始路径,那么我们可以找一些特殊字符绕过路径判断,并且不影响整体接口,比如:分号 ; ,正斜杠 / 等等。

最终,构造结构路径为 /;/admin/test 或 ///admin/test ,这样路径就不是以 /admin 开头了,并且该路径不会影响结构访问,实现了权限绕过。

为什么是分号和正斜杠?

当然还有一些其他字符,编码呀也可以进行绕过。

但我们可以首先使用分号(;)进行尝试,在 URL 中有一个保留字符分号(;),主要作用是作为参数分隔符进行使用的。

4.2 漏洞验证

代码审计侧发现了后端存在权限绕过后漏洞。

首先,我们登陆后台寻找一个后台接口,比如商品管理接口,访问如下图所示:

然后,我们删除 Cookie 后,也就是没有访问权限了,发送数据包,显示需要跳转到登录页面,如下图所示:

最后,我们利用代码审计中权限绕过小技巧,使用分号(;)构造请求接口,最终为

http://127.0.0.1:28089/;/admin/goods/list?

_search=false&nd=1685517654136&limit=20&page=1&sidx=&order=asc ,可以发现成功绕过了权限认证,获取到了商品内容,如下图所示:

5 前台越权漏洞代码审计

5.1 前台越权漏洞代码审计

在做这部分代码审计分析时,我们需要改动两处代码,打开注册功能。

第一处,访问 src/main/java/ltd/newbee/mall/controller/mall/PersonalController.java 代码,将注册功能代码注释删除,最终如下图所示:

第二处,访问 src/main/resources/templates/mall/register.html ,将注册事件按钮改为register(),如下图所示:

接下来,访问前台注册页面,注册一个账号后,进入个人中心功能,发现存在一个 更改个人信息 的功能,点此功能,同时使用 BurpSuite 获取数据包,如下图所示:

发现数据包中存在 userId,怀疑存在越权漏洞,我们通过代码审计进行分析。

在项目中全局搜索接口名 /personal/updateInfo ,最终找到代码位置,如下图所示:

我们进入 PersonalController.java,该代码位于

src/main/java/ltd/newbee/mall/controller/mall/PersonalController.java ,该接口的Controller 层代码如下图所示:

下面,我们进入代码审计分析阶段。

第一步:分析第 116 行,通过方法名也可以看出这是更新用户信息的方法,其中传入了 mallUser和 httpSession 参数,而这两个参数来自用户, MallUser mallUser 表示要更新的用户对象,也就是接受用户信息的实体类, HttpSession httpSession 表示当前会话的 HttpSession 对象。

我们可以跟进 MallUser 查看,主要定义了以下内容,其中有个 userId,如下图所示:

第二步:返回到 PersonalController 层,Ctrl 加鼠标左键点击第 116 行的 updateUserInfo 跟进该方法,最终跳转到了 NewBeeMallUserService 层,如下图所示:

点击左侧按钮,进行跟进到 NewBeeMallUserServiceImpl 层,updateUserInfo 方法具体代码如下:

第三步:分析实现层代码具体做了什么操作。

第 73 行,根据根据用户 ID 主键查询用户信息,跟进 selectByPrimaryKey 通过 MallUserMapper.java

接口跳转到 MallUserMapper.xml 映射器代码中。可以看到,通过限制 userId 在tb_newbee_mall_user 表中查询用户信息。也就是说,我的 userId 是 10,则最终查询语句如下,代码

如下图所示:

select refid="Base_Column_List"(在上面定义了具体是哪些列) from tb_newbee_mall_user
where user_id = 10;

总结来说,第 73 行的作用是通过 ID 查询用户信息并赋值给 user。第 74 ~ 77 行,如果 user 不为 null,进行了三个 set 操作,其中传入的参数是来自 mallUser。也就是说,将查询到的用户信息中的内容设置成了用户输入的内容了。如下图所示:

第 78 行是关键,通过调用 mallUserMapper.updateByPrimaryKeySelective(user) 方法,将更新后的用户信息保存到数据库。如果更新操作影响的行数大于 0,则执行下面的代码块。我们跟进该方法,通过 MallUserMapper.java 接口跳转到 MallUserMapper.xml 映射器代码中。在这里面我们主要更新了nick_name,address 以及 introduce_sign 这三个是我们传入的参数,不为 null。如下图所示:

第 79 ~ 83 行,是上面代码判断操作是否大于 0,符合该条件则进入这几行代码,我们更新个人信息是否

符合这个条件的。这几行代码大致意思是,获取更新的用户信息,然后返回更新成功的响应。

第四步:整个流程我们追踪完了,总得来说,就是通过传入的 userId 获取用户信息后进行信息更新

操作。整个流程没有任何权限校验,没有判断 userId 所属关系,进而造成了越权漏洞。

5.2 漏洞验证

根据代码审计部分,我们确定了更改个人信息功能存在越权漏洞。

下面我们进行漏洞验证。

首先,访问注册接口 http://127.0.0.1:28089/register ,自行注册两个用户。

然后,登录其中一个账户,访问个人中心下个人信息功能,点击更改个人信息,键入所需信息后,点击确认,此时使用 BurpSuite 拦截抓取数据包,可以看到该账号的 userId 为 6,如下图所示:

再然后,登录另一个账号,同样访问上述功能,使用 BurpSuite 抓取数据包,将其发到 Repeater 模块下,如下图所示:

再再然后,将数据包中的 userId 改为 9,及另一个账号的 ID,发送数据包,同样显示修改成功,如下图

所示:

最后,登录最开始的账号,访问个人信息功能,可以看到信息已经被越权修改了,如下图所示:

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值