漏洞简介
binary.do接口的TableName参数对传入的数据没有充足的校验,导致该接口存在SQL注入漏洞,未授权的攻击者可获取数据库敏感信息。
资产测绘搜索语句
hunter:web.body="/newsedit/newsedit/"
路由与鉴权分析
通过分析web.xml配置文件,我们可以发现以下路由定义。
这里将所有以 .do
结尾的请求映射到 e5
Servlet。
定义了一个名为 e5
的 Servlet,它是 Spring MVC 的 DispatcherServlet
,用于处理应用的 HTTP 请求。并且通过 load-on-startup
的配置, 将在应用启动时被优先加载。
其中定义了一系列过滤器,我们可以发现如下配置,这里配置了关于URL 入口检查的过滤器,我们知道<init-param>
元素用于定义初始化参数,这里session-not-checked
参数看名字可以知道指定了不需要进行会话检查的请求路径列表。
其中就有binary.do路由,这里对这些登录、获取资源的路由进行绕过会话检查减少服务器负担。
漏洞分析
查看相应漏洞路由代码进行分析。首先通过DBSession sess;IResultSet rs;
分别获取数据库会话和查询结果集。通过getInt(request, "KeyID", 0)
方法从请求中获取 KeyID
参数,然后进行判断如果 KeyID
为 0,就返回空响应。所以传入的 KeyID
不能为0。
随后通过get(request, "TableName");
方法,获取表名get(request, "KeyName");
获取主键名 get(request, "FieldName");
获取字段名。然后将其拼接进sql0
参数的sql语句中,通过sess = Context.getDBSession();
获取数据库会话,最后通过sess.executeQuery(sql0, new Object[]{new Integer(keyID)});
方法执行 SQL 查询。
通过以上分析我们可以发现传入的相应参数未经过任何过滤,直接拼接sql语句中。继续跟进executeQuery
方法,可以发现最后sql语句执行被prepareStatement
方法预编译,那是否就不存在sql注入呢?
回到sess.executeQuery(sql0, new Object[]{new Integer(keyID)});
方法,这里执行的操作是执行一个 SQL 查询,并传递查询参数。其中查询的参数为keyID
,通过前面我们知道执行的SQL查询语句sql0
为 " select " + fieldName + " from " + tableName + " where " + keyName + " = ?";
这里的?为后续预编译的占位符,也就是我们的查询参数keyID
会被预编译无法进行sql注入。但根据前面的分析可知我们的注入点不止keyID
这一个参数fieldName
,tableName
,keyName
,都是从请求中获取的参数。
继续分析后续代码的流程,我们可以知道该路由主要功能是根据传入的参数从数据库中查询图像路径,并将对应的图像文件发送到客户端。
所以这里的查询不会有回显。这里我们通过tableName
参数进行注入并通过UNION
用于将注入利用的SELECT
语句进行合并,达到sql注入的利用。
漏洞复现
由于无回显,这里我们使用WAITFOR DELAY ‘0:0:5’;
使当前SQL语句执行延迟5秒进行时间盲注。可以看到响应时间超过5秒,sql语句执行了。