在 .NET 应用程序中,安全漏洞时常成为攻击者突破防线的关键入口。近日,一项全局绕过漏洞的发现引起了广泛关注。该漏洞源自两个组件的协同作用,攻击者只需构造一个特定的URL请求,便能实现对任意接口的未授权访问。
某和OA协同办公管理系统软件共有20多个应用模块,从功能型的协同办公平台上升到管理型协同管理平台,并不断的更新完善,全面支撑企业发展。此系统外部已公开的多个漏洞详情,不难发现都有一些共同的特点,那就是URL里的 .aspx后都会加上一个 / ,然后再进行传递参数。
比如 /RssModulesHttp.aspx/?interfaceID=1,为此有一些对.NET感兴趣的群友们在星球陪伴的微信群里问起这个原因。于是笔者带着群友们这些疑问点抽空研究总结了一下,于是便有了此文。
1.1 无扩展名方式
如果觉得图上XML代码看不清楚的话,也可以参考如下这段Web Handler以及Modules配置详情。
<modules runAllManagedModulesForAllRequests="true"><add name="JHSoft.CustomQuery" type="JHSoft.CustomQuery.HttpUploadModule, JHSoft.CustomQuery"></add><add name="HttpUploadModule" type="JHWeb.qqfly.Upload.HttpUploadModule, JHWeb.qqfly.Upload"></add><add name="JHSoft.Log" type="JHSoft.Log.LogHttpModule, JHSoft.Log"></add></modules><handlers accessPolicy="Read, Script"><remove name="ExtensionlessUrlHandler-Integrated-4.0"></remove><remove name="OPTIONSVerbHandler"></remove><remove name="TRACEVerbHandler"></remove><add name="AjaxMethod" verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax"></add><add name="scissors" path="scissors.axd" verb="*" type="BitmapCutter.Core.HttpHandler.BitmapScissors,BitmapCutter.Core"></add><add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"></add></handlers>
上述配置中,我们发现了一个名为ExtensionlessUrlHandler的一般处理程序。关于此handle背景知识是这样的:.NET WebForms框架早期版本中对于URL请求的设计和管理一直沿用经典的ASP风格,通常URL地址上包含文件及扩展名,比如 UserName.aspx、CheckUser.ashx 等。
随着 Web 开发的进步和用户体验需求的提升,陆续出现像MVC框架对无扩展名 URL的需求,即 extensionless URL。
1.2 IIS配置映射
比如常见的 /Mall/Product/GetById/10 ,使用该组件时需要当运行在IIS7以上版本,配置Web.config后将会正常处理上面这种 extensionless URL。IIS经典模式用的是aspnet_isapi.dll,映射DefaultHttpHandler进行处理,如下配置所示。
<system.webServer><handlers><add name="ExtensionlessUrl-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG" modules="IsapiModule"scriptProcessor="%WINDIR%Microsoft.NETFrameworkv4.0.30319aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0"/></handlers></system.webServer>
集成模式下会映射到System.Web.Handlers.TransferRequestHandle来处理,某和OA便使用此方法进行映射。如下配置所示。
<system.webServer><handlers><remove name="ExtensionlessUrlHandler-Integrated-4.0"/><remove name="OPTIONSVerbHandler"/><remove name="TRACEVerbHandler"/><add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/></handlers></system.webServer>
这段配置中path="*." 匹配所有无扩展名的 URL 请求,verb="*" 表示谓词,就是IIS处理所有 HTTP 请求方法,包含了GET/POST/DELETE/PUT 等。
ExtensionlessUrlHandler 的引入就是为了满足当时WebForms应用具备现代 Web 架构对无扩展名 URL 的需求。随着.NET后续版本的迭代和更新,Web框架已不再需要此项配置便可实现无扩展名的URL。
我们知道在 .NET 应用程序中,HTTP Modules用于处理进入的 HTTP 请求的生命周期事件。通过自定义 HTTP Modules可以为应用程序添加日志记录、安全验证防护等功能。在企业级应用某和OA中,我们可以看到对 HTTP 模块做了如下配置,例如:
<modules runAllManagedModulesForAllRequests="true"><add name="JHSoft.Log" type="JHSoft.Log.LogHttpModule, JHSoft.Log"></add></modules>
上述配置指定HTTP请求需要经过JHSoft.Log.LogHttpModule模块,从名称上看应该是记录请求等日志数据的,其实反编译后发现不仅做了日志的处理,还有对整个请求做了安全校验。具体代码如下所示。
publicclassLogHttpModule:IHttpModule{publicvoidInit(HttpApplication application){ application.BeginRequest +=this.Application_BeginRequest; application.AcquireRequestState +=this.application_AcquireRequestState; application.EndRequest +=this.Application_EndRequest; application.Error +=this.application_Error;}}
Init 方法用于初始化自定义的模块,并注册一系列事件处理程序,其中AcquireRequestState事件在获取当前请求的状态时触发,常用于检查请求的数据。具体定义如下所示。
privatevoidapplication_AcquireRequestState(object sender,EventArgs e){HttpApplication httpApplication =(HttpApplication)sender;HttpContext context = httpApplication.Context;string text = context.Request.Path.ToLower();if(!text.EndsWith(".aspx")){ text.EndsWith(".ashx");}if(text.EndsWith(".aspx")){if(this.SqlFilter(context.Request)){ context.Response.Write("传递的字符中含有敏感字符,操作已停止。"); context.Response.End();}}
代码中对aspx做了深入的处理,通过 context.Request.Path.ToLower(); 获取请求路径并转换为小写,然后text.EndsWith(".aspx") 判断请求路径是否以 .aspx 结尾,如果是则调用 SqlFilter 方法检查请求是否包含敏感字符,这是一个防御SQL注入的方法。这么看如果是.ashx或者.asmx文件有注入漏洞则完全不受该约束,可以顺利的进行SQL注入攻击。
如果没有注入的风险,程序会继续向下执行,通过 if ((context.Session == null || context.Session["UserCode"] == null) ... 检查会话是否为空。
接着通过类似的判断text.IndexOf("/jhsoft.web.login/password.aspx") == -1 排除特定的页面,除此之外所有的请求都会被强制重定向至登录页,如下图所示。
if((context.Session null|| context.Session["UserCode"]null)&& text.IndexOf("/jhsoft.web.login/password.aspx")-1&& text.IndexOf("/jhsoft.web.login/passwordmode.aspx")-1&& text.IndexOf("/jhsoft.web.login/newpass.aspx")-1&& text.IndexOf("/jhsoft.web.epass/epasslogin.aspx")-1&& text.IndexOf("/jhsoft.web.epass/epassloginverify.aspx")-1&& text.IndexOf("/jhsoft.web.epass/epasspersonrepin.aspx")-1&& text.IndexOf("/jhsoft.web.login/installationcontrol.aspx")-1&& text.IndexOf("/jhsoft.web.login/clientcheck.aspx")-1){string[] array = text.Split(newchar[]{'/'});if(array.Length 6){ context.Response.Redirect("../../../JHSoft.Web.Login/PassWord.aspx");}elseif(array.Length 5){ context.Response.Redirect("../../JHSoft.Web.Login/PassWord.aspx");}else{ context.Response.Redirect("~/JHSoft.Web.Login/PassWord.aspx");}}
经过上面两小节的分析得知,某和OA支持像MVC那样无扩展名的路由请求,而在全局用于检查的AcquireRequestState事件中错误的使用了EndsWith方法判断URL请求是否包含.aspx。
因此,我们可以构造出如下请求达到绕过全局的校验。比如输入/SetImageModule.aspx/id/121212,或者使用 /SetImageModule.aspx/?id=2222 均可以实现未授权访问。效果如下图所示。
GetRssInfo 方法用于从数据库中获取特定 RSS 接口的信息。它使用传入的 interfaceID 参数来查询数据库中的 WFRssModule 表,并返回查询结果,具体代码如下图所示。
小结
专属福利
1. 学习模式: 代码审计知识星球在线录播视频 +后续漏洞挖掘直播、内部专属交流社区答疑解惑;
2. 优享福利:加入.NET代码审计星球后赠送永久dot.Net安全基础入门星球。
欢迎对.NET代码审计关注和关心的同学加入我们 [dot.Net安全代码审计] ,目前已有近 100+ 位朋友抢先预定。
星球门票后期价格随着内容和质量的不断沉淀会适当提高,越早加入越划算! 现在加入星球可享受星球早鸟价,并可领取100元优惠券,期待在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事,可扫描下方老师二维码了解更多详情。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...