经验交流|系统安全修正|避免反射调用执行程序删除我的文件和目录
摘要:
1、我网站有个在线测试功能,通过Ajax调用后台一个方法并返回方法
2、后台的方法是eKing.EkUtil.Helpers.eKingEkUtilHelper,一个工具类
3、工具类里面有文件/目录的删除操作
4、我用ExampleUtilHandler做Ajax中转反射调用eKingEkUtilHelper里面的方法
5、(安全漏洞)如果别人知道我的规则和文件操作的方法名,外部执行就有可能读取我的服务器文件内容或删除我服务器的文件
6、修正方式(见下文)
原文链接:
一、在线测试功能样例:
在线示例的JavaScript代码
function GetAjaxData() { var ajxData = []; ajxData.push({ name: "DllName", value: "eKing.EkUtil" }); ajxData.push({ name: "MethodName", value: "IdCardNumberToStar" }); var MP1 = CtrlGetValue("txt_Input", false, false); ajxData.push({ name: "ParamsCount", value: "1" }); ajxData.push({ name: "_MP1", value: MP1 }); return ajxData; } // 确定操作 // function OkOper() { var ajxData = GetAjaxData(); var ajaxUrl = GlobalPhyPath + "/Handlers/ExampleUtilHandler.ashx"; $.ajax({ cache: false, async: true, url: ajaxUrl, data: ajxData, type: "post", success: function(data) { var outputCtrl = document.getElementById("txt_Result"); outputCtrl.value = data; document.getElementById("span_exectime").innerHTML = new Date(); } }); }
示例链接:
二、eKingEkUtilHelper工具类的方法
三、ExampleUtilHandler的逻辑代码
ExampleUtilHandler.ashx原逻辑代码
<%@ WebHandler Language="C#" Class="ExampleUtilHandler" %> using System; using System.Web; using System.Collections.Generic; public class ExampleUtilHandler : IHttpHandler { /// <summary> /// /// </summary> /// <param name="context"></param> public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; string theResult = null; try { theResult = ToResult(context, null); } catch (Exception err) { theResult = "[系统异常]:" + err.Message; } // 编码格式 // context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312"); // System.Text.Encoding.UTF8; context.Response.Write(theResult); } /// <summary> /// List-string的值转成object[] - ListStringToObjArray + /// </summary> /// <param name="sList"></param> /// <returns></returns> protected object[] ListStringToObjArray (System.Collections.Generic.List<string> sList) { int iCount = sList.Count; object[] p = new object[iCount]; for (int i = 0; i < iCount; ++i) { p[i] = sList[i]; } return p; } /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="paramsSize"></param> /// <returns></returns> protected List<string> ListStringParamsGet(HttpContext context, int paramsSize) { List<string> theResult = new List<string>(); string str = null; int paramsSizeAddOne = paramsSize + 1; for (int i = 1; i < paramsSizeAddOne; ++i) { str = context.Request.Form["_MP" + i.ToString()]; theResult.Add(str); } return theResult; } /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="xdbHelper"></param> /// <returns></returns> protected string ToResult(HttpContext context, SlowX.DAL.Helpers.DBHelper xdbHelper) { string methodName = context.Request.Form["MethodName"]; if (methodName == null || methodName.Length == 0) { return "[系统异常]:方法名不能为空。"; } string dllName = context.Request.Form["DllName"]; int paramsSize = int.Parse(context.Request.Form["ParamsCount"]); List<string> pList = ListStringParamsGet(context, paramsSize); Type utType = null; object ut = null; string lowerDllName = null; if (dllName == null) lowerDllName = ""; else lowerDllName = dllName.Trim().ToLower(); switch (lowerDllName) { case "slowx.createcodeexampleutil": SlowX.CreateCodeExampleUtil.Helpers.CreateCodeExampleUtilHelper createCodeExampleUtil = SlowX.CreateCodeExampleUtil.Helpers.CreateCodeExampleUtilHelper.GetInstance(); utType = createCodeExampleUtil.GetType(); ut = createCodeExampleUtil; break; case "slowx.createcodeutil": SlowX.CreateCodeUtil.Helpers.SlowXCreateCodeUtilHelper createCodeUtil = SlowX.CreateCodeUtil.Helpers.SlowXCreateCodeUtilHelper.GetInstance(); utType = createCodeUtil.GetType(); ut = createCodeUtil; break; case "eking.ekutil": eKing.EkUtil.Helpers.eKingEkUtilHelper ekUtil = eKing.EkUtil.Helpers.eKingEkUtilHelper.GetInstance(); utType = ekUtil.GetType(); ut = ekUtil; break; case "slowx.tool": SlowX.Tool.Utils.Util tool = SlowX.Tool.Utils.Util.GetInstance(); utType = tool.GetType(); ut = tool; break; default: SlowX.ExampleUtil.Utils.Util utH = SlowX.ExampleUtil.Utils.Util.instance; utType = utH.GetType(); ut = utH; break; } System.Reflection.MethodInfo mi = utType.GetMethod(methodName); if (mi == null) { return "没有找到对应的方法"; } object[] p = ListStringToObjArray(pList); object obj = mi.Invoke(ut, p); if (obj == null) return "null"; return obj.ToString(); } public bool IsReusable { get { return false; } } }
安全漏洞:
(1)DllName:eKing.EkUtil
(2)MethodName:FileDelete
(3)参数:文件路径
就有可能通过Ajax执行删除我服务器的文件
四、修正方式
就有可能通过Ajax执行删除我服务器的文件
修正后的eKingEkUtilHelper
using eKing.EkUtil.IHelpers; using System; using System.Collections.Generic; using System.Reflection; namespace eKing.EkUtil.Helpers { /// <summary> /// /// </summary> public partial class eKingEkUtilHelper : IeKingEkUtilHelper { /// <summary> /// /// </summary> protected readonly static eKingEkUtilHelper m_instance = new eKingEkUtilHelper(); /// <summary> /// /// </summary> /// <returns></returns> public static eKingEkUtilHelper GetInstance() { return m_instance; } /// <summary> /// /// </summary> public eKingEkUtilHelper() { } /// <summary> /// List-string的值转成object[] - ListStringToObjArray + /// </summary> /// <param name="sList"></param> /// <returns></returns> protected object[] ListStringToObjArray (System.Collections.Generic.List<string> sList) { int iCount = sList.Count; object[] p = new object[iCount]; for (int i = 0; i < iCount; ++i) { p[i] = sList[i]; } return p; } /// <summary> /// 反射调用 /// </summary> /// <param name="methodName"></param> /// <param name="pList"></param> /// <returns></returns> public string InvokeCall(string methodName, List<string> pList) { if (methodName == null || methodName.Length == 0) { throw new Exception ( "方法:" + MethodBase.GetCurrentMethod().ReflectedType.FullName + " " + MethodBase.GetCurrentMethod().ToString() + " 发生异常:" + "传入的字符串参数:" + "methodName" + "为null或为空。" ); } methodName = methodName.Trim(); if (methodName.Length == 0) { throw new Exception ( "方法:" + MethodBase.GetCurrentMethod().ReflectedType.FullName + " " + MethodBase.GetCurrentMethod().ToString() + " 发生异常:" + "传入的字符串参数:" + "methodName" + "为null或为空。" ); } string lowerMethodName = methodName.Trim().ToLower(); switch (lowerMethodName) { case "dirdelete": case "dircreatebyfullfilename": return methodName+"方法不允许执行"; default: break; } Type utType = this.GetType(); System.Reflection.MethodInfo mi = utType.GetMethod(methodName); if (mi == null) { return "没有找到对应的方法"; } object[] p = ListStringToObjArray(pList); object obj = mi.Invoke(this, p); if (obj == null) return "null"; return obj.ToString(); } } }
修正后的ExampleUtilHandler
<%@ WebHandler Language="C#" Class="ExampleUtilHandler" %> using System; using System.Web; using System.Collections.Generic; public class ExampleUtilHandler : IHttpHandler { /// <summary> /// /// </summary> /// <param name="context"></param> public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/plain"; string theResult = null; try { theResult = ToResult(context, null); } catch (Exception err) { theResult = "[系统异常]:" + err.Message; } // 编码格式 // context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312"); // System.Text.Encoding.UTF8; context.Response.Write(theResult); } /// <summary> /// List-string的值转成object[] - ListStringToObjArray + /// </summary> /// <param name="sList"></param> /// <returns></returns> protected object[] ListStringToObjArray (System.Collections.Generic.List<string> sList) { int iCount = sList.Count; object[] p = new object[iCount]; for (int i = 0; i < iCount; ++i) { p[i] = sList[i]; } return p; } /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="paramsSize"></param> /// <returns></returns> protected List<string> ListStringParamsGet(HttpContext context, int paramsSize) { List<string> theResult = new List<string>(); string str = null; int paramsSizeAddOne = paramsSize + 1; for (int i = 1; i < paramsSizeAddOne; ++i) { str = context.Request.Form["_MP" + i.ToString()]; theResult.Add(str); } return theResult; } /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="xdbHelper"></param> /// <returns></returns> protected string ToResult(HttpContext context, SlowX.DAL.Helpers.DBHelper xdbHelper) { string methodName = context.Request.Form["MethodName"]; if (methodName == null || methodName.Length == 0) { return "[系统异常]:方法名不能为空。"; } string dllName = context.Request.Form["DllName"]; int paramsSize = int.Parse(context.Request.Form["ParamsCount"]); List<string> pList = ListStringParamsGet(context, paramsSize); string lowerDllName = null; if (dllName == null) lowerDllName = ""; else lowerDllName = dllName.Trim().ToLower(); switch (lowerDllName) { case "slowx.createcodeexampleutil": SlowX.CreateCodeExampleUtil.Helpers.CreateCodeExampleUtilHelper createCodeExampleUtil = SlowX.CreateCodeExampleUtil.Helpers.CreateCodeExampleUtilHelper.GetInstance(); return createCodeExampleUtil.InvokeCall(methodName, pList); case "slowx.createcodeutil": SlowX.CreateCodeUtil.Helpers.SlowXCreateCodeUtilHelper createCodeUtil = SlowX.CreateCodeUtil.Helpers.SlowXCreateCodeUtilHelper.GetInstance(); return createCodeUtil.InvokeCall(methodName, pList); case "eking.ekutil": eKing.EkUtil.Helpers.eKingEkUtilHelper ekUtil = eKing.EkUtil.Helpers.eKingEkUtilHelper.GetInstance(); return ekUtil.InvokeCall(methodName, pList); case "slowx.tool": SlowX.Tool.Utils.Util tool = SlowX.Tool.Utils.Util.GetInstance(); return tool.InvokeCall(methodName, pList); default: SlowX.ExampleUtil.Utils.Util utH = SlowX.ExampleUtil.Utils.Util.instance; return utH.InvokeCall(methodName, pList); } } /// <summary> /// /// </summary> public bool IsReusable { get { return false; } } }