项目技术分析
通过项目结构,能够看出来使用的技术为前后端分离。在看readme文档可以发现,技术框架分别有:
1 | * 核心框架:SpringBoot 2.0.0 |
关于了解系统所使用的开源组件技术的两种情况:
1.maven项目,打开pom文件查看。带着通用性漏洞的功底针对性寻找突破口。
2.传统老项目,直接到web-inf下查看jar包。
漏洞审计
SQL注入
- 全局搜索在特定关键字in,like,order by ,group by是否使用了直接拼接的方式(重点)
- 全局搜索$在mybatis是否使用,全局搜索+在jdbc或Hibernate是否使用,对于自己封装的数据库操作的增删改查的方法特殊看待。
- 查看第三方组件的漏洞(重点)
对于maven项目,直接查看pom.xml中是否应用了公开的开源组件存在通用性漏洞。
1 | <dependency> |
1 | <dependency> |
既然是mybatis,我们可以很快速的通过是否有$来判断是否存在不安全的拼接,通过限定后缀为xml进行搜索。
比如这里就可以看出有许多不安全的拼接。
我们选一个有可能有注入的UserMapperEX进行查看。
可以看到username和login_name都使用了模糊搜索,接下来就是向上回溯,判断回溯点是否可控。
通过全局搜索发现该方法被UserService.java的select方法调用,而select方法被resourceController.java的getlist调用。
1 | public String getList(@PathVariable("apiName") String apiName, |
getlist顾名思义就是一个查询数据列表的功能,apiName是一个变量,会根据不同的值查询不同的数据。当值为User时,会查询用户数据,从而触发之前有问题的sql语句的调用。
让我们在之前的select函数中打上断点,然后从前台访问中,发现点击用户管理时,触发了断点。
也可以从抓到的包中发现与getlist方法的参数相对应。其中有PageSize,CureentPage,search。
而search参数经过了特殊处理。以{}
格式进行了包装。
因此我们可以构造以下poc:
1 | {"userName":"' or 1=1 and '1%'='1","loginName":""} |
注入成功
webfilter绕过
Webfilter是一个Tomcat组件,用于拦截我们指定的url,当请求发送到Tomcat服务器时,会调用拦截器的doFilter方法进行判断。
1 | public void doFilter(ServletRequest request, ServletResponse response, |
这里可以发现,如果url中包含了/doc.html
,/register.html
,/login.html
则直接跳过了当前的filter,转到下一个filter当中。(下一个chain.filter是没有做过滤的)
所以这里可以清除一下cookie,使用以下url并进行抓包
1 | /doc.html/../user/list?search=%7B%22userName%22%3A%22%22%2C%22loginName%22%3A%22%22%7D¤tPage=1&pageSize=15 |
依然查询成功。
Fastjson反序列化
fastjson的核心就在于调用了fastjson.JSON的parseObject函数讲json字符串反序列化成对象,搜一下parseObject,可以发现遍地开花,其中有一个getinfo是在utils下的。
1 | public static String getInfo(String search, String key){ |
发现可以在UserComponent
里找到
1 | private List<?> getUserList(Map<String, String> map)throws Exception { |
这时候可以用1.2.55的payload测试一下。
1 | {"@type":"java.net.Inet4Address","val":"x4ht4h.dnslog.cn"}¤tPage=1&pageSize=15 |
dnslog收到请求。
失败的越权
越权漏洞审计的思路:
- 需要熟悉主要的功能模块。
- 需要确定系统所使用的权限控制技术,例如springsecurity,shiro以及手动编写的filter过滤器。
越权漏洞主要分为两个维度,一个是接口授权的问题,另一个是数据鉴权的问题。
通过合理的权限控制技术来动态的将所有的用户和角色绑定起来,将所有的角色和权限绑定以来,来解决接口授权不到位的问题。
通过分析实际的功能和业务需求,在具体的业务方法里面进行数据鉴权,最终落地到sql查询条件的限制以及角色的控制。
在重置密码功能中有以下功能:
1 |
|
会默认把密码设置为123456。
1 | public int resetPwd(String md5Pwd, Long id) throws Exception{ |
其中只对admin进行了鉴权,使其不能重置超管密码,但是对其他用户都可以使用更改。接下来以为这是一个轻而易举的越权漏洞,但是在测试的时候发现同角色的用户修改他人密码不成功的情况。这是因为在执行sql语句的时候会多一句
1 | <include refid="Base_Column_List" /> |
该方法会拼接一个条件jsh_user.tenant_id=xxx。后经查询知道该字段是mybatisplus自动为防止越权漏洞设置的技术。因此未设置越权。
(147条消息) Mybatis-plus如何实现自动添加租户ID,Insert操作时怎么自动添加tenant_id字段_jianghx1024的博客-CSDN博客_mybatis tenant