service SQL 注入漏洞
未授权接口寻找
在前面的文章中我们可以知道,系统的鉴权依赖于shiro,在spring-context-shiro的XML配置定义了一个叫做shiroFilterChainDefinitions
的Spring bean,它是一个String
类型的bean,用于定义Apache Shiro框架用于URL模式匹配的权限和访问控制规则。
在配置文件中,是通过定义一个类型为java.lang.String
的bean来声明这些规则。每个规则是由一行组成的,格式是“pattern = filterName”,其中pattern是一个Ant风格的路径模式,而filterName是过滤器的名称,决定了访问该模式的路径时所执行的安全检查。
其中anon
(匿名)表示这个路径下的资源不需要认证或授权,任何人都可以访问。于是我们就可以发现系统中的未授权接口,再结合web.xml
文件中,通过配置的servlet,可以快速定位到未授权接口的相应代码。
漏洞分析
通过分析我们可以发现/slogin/service* = anon
接口是配置的匿名访问,在web.xml配置文件中寻找/slogin/service*
路由。
可以发现配置的servlet及其映射关系,查看相应代码。
内容不多,通过分析我们可以知道LoginServiceDispatcher
类继承自HttpServlet
,进行处理HTTP请求。并且重写了HttpServlet的service
方法,它是处理请求的核心方法。如何从HTTP请求头中获取名为"service"的参数,首先会检查请求参数中是否存在名为service
的参数,并且这个参数不应该为空。如何根据参数值调用DBServiceImpl的不同方法处理请求。
当service
参数等于"db.select
",调用DBServiceImpl的select方法处理请求,查看代码分析。
方法会先将HTTP请求参数转换为JSON对象,JSONObject paramJSONObject = FormUtils.toJsonParam(request);
再从JSON对象中获取键为"sql"的值 String sql = paramJSONObject.getString("sql");
进行判断如果SQL语句是一个SELECT查询,直接执行SQL查询,获取结果集 rs = db.getStatement().executeQuery(sql);
。
未对sql语句进行任何判断和过滤,直接使用来自请求的SQL语句来执行查询,造成了SQL注入。
漏洞分析
至此我们可以构造poc,params={"sql":"select 语句"},查询任意数据。
validateLoginName SQL注入漏洞
未授权接口寻找
通过前面的方法,我们可以找到/sys/user/validateLoginName接口也是配置的匿名访问。
同时从web.xml配置来看,我们可以知道这个应用使用了Spring框架进行Web开发,配置了多个Servlet用于不同的功能。
漏洞分析
通过全局搜索我们可以知道其中/sys/user/validateLoginName
接口,属于Spring MVC中定义的控制器(Controller)。
这里@RequestMapping
注解将HTTP请求映射到MVC和REST控制器的处理方法上。任何直接调用了一个名为userDao的对象的findUniqueByProperty方法,在系统中使用了MyBatis框架。
T findUniqueByProperty(@Param("propertyName") String str, @Param("value") Object obj);
是MyBatis Mapper接口中的一个方法声明,当我们搜索SQL映射文件时,有多个文件。但我们这里调用的是userDao的对象,查看userDao.xml。
<select id="findUniqueByProperty" resultType="User"
statementType="STATEMENT">
select *
from sys_user
where ${propertyName} = '${value}'
AND del_flag = '0'
</select>
可以发现SQL查询语句,是用于从数据库表sys_user中进行检索数据。'${value}'
是参数占位符,用于动态替换与属性名对应的值。在MyBatis框架中#{value}是进行预编译参数的替换,这样可以避免SQL注入。而这里使用'${value}'
,相当于直接将参数拼接进入sql语句,导致了SQL注入漏洞。
在/sys/user/validateLoginName
接口中返回类型是boolean,得不到回显所以这里我们不能直接进行查询得到数据,只能进行时间或布尔盲注。