dotnet代码审计系列(一)
1. 概述
1.1. 背景
.NET Framework是Microsoft开发的托管代码框架,主要用于构建和运行Windows应用程序。它提供了大量的类库,通用语言运行时(CLR)以及用于开发和管理应用程序的工具。使用.NET框架开发的应用程序通常用C#,VB.NET,F#和其他语言编写。汇编后,它们生成中间语言(ILS),然后由CLR执行。.NET框架的重要特征包括:
跨语言互操作性:用不同的编程语言编写的组件可以无缝协作,因为它们都将其编译为IL并在CLR中运行。
内存管理:通过垃圾收集器自动管理内存,以减少内存泄漏和其他与内存有关的安全问题。
安全模型:NET框架提供代码访问安全性(CAS)和验证机制,控制代码的权限和执行。
在企业应用程序中,NET框架被广泛用于Web应用程序,桌面应用程序和服务的开发。在今年的国家HW中,许多应用程序仍然使用.NET框架。由于其广泛使用和应用程序的复杂性,NET应用程序很容易被攻击者瞄准。当前,关于.NET框架代码审核的市场信息较少,因此我将总结本文。
1.2. .NET Framework与.NET Core的区别
.NET和.NET Core是Microsoft开发的两个不同的开发框架,具有以下差异:平台支持
.NET Framework (.NET):仅支持在Windows操作系统上运行。适用于开发Windows桌面应用程序,ASP.NET Web应用程序等。.NET Core:是一个可以在Windows,Linux和MacOS上运行的跨平台框架。因此,它更适合需要跨平台部署的应用程序。
开源与社区支持
.NET Framework:不是完全开源的,尽管其某些组件是开源的,但总体框架仍然由Microsoft维护和控制。.NET Core:是完全开源的,具有活跃的开源社区。开发人员可以访问源代码并为其做出贡献。
简而言之,NET Core是一个更现代,跨平台,模块化框架,更适合现代应用的开发需求。NET框架主要用于维护和持续开发现有Windows应用程序。随着.NET 5+的发布,Microsoft将.NET Core作为未来的主要开发方向,并统一了整个.NET生态系统。
2. .NET Web 项目
目前,ASP.NET中的三种主流开发方法是:ASP.NET WebForm,ASP.NET MVC和ASP.NET Core。拍摄正式图片以描述:

2.1. WebForm开发模式
一张经典图片来描述整个过程:
ASPX页面显示代码通常是一些HTML代码。文件标头的第一行将显示特定的触发功能代码,因此您可以通过此位置找到处理功能。服务器端操作是在ASPX.CS文件中定义的
.CS是一个存储公共类的类文件。
.ASHX是一家通用处理程序,主要用于编写Web处理程序,可以将其理解为不会显示的ASPX页面,但更有效
DLL是编译的CS文件。
以WebGoat.net射击范围为例:

第一行的含义:
语言:代表当前使用的语言并为C#开发。
AutoEventWireup:一种事件处理方法,该方法指示ASP.NET是否会自动将页面事件(例如page_load)绑定到页面。 true表示自动绑定,这意味着,如果页面中有一个名为page_load的方法,它将自动处理页面的加载事件。
CodeBehind:该属性指定了与该页面关联的代码范围文件的路径。在上面的图像中,loginpage.aspx.cs是一个包含定义页面逻辑的背景代码的文件。在一些较新的ASP.NET项目中,CodeBehind可以被CodeFile替换,尤其是在Web应用程序项目中。
继承:指定页面继承的类。此页面从Owasp.webgoat.net.loginpage类继承,该类通常在loginpage.aspx.cs文件中定义。
目录结构:
1
2
3
4
5
App_Code:存储共享的代码文件,例如类,接口等。这些文件在整个应用程序中可访问。
APP_DATA:存储应用程序的数据库文件或其他数据文件。外部用户无法访问此目录。
BIN:存储编译的组件(DLL文件)和依赖项。该目录将自动创建。
Resources:存储与特定页面相关的资源文件。
web.config:应用程序配置文件用于定义应用程序设置,连接字符串,路由等。
2.2. MVC 开发模式
ASP.NET MVC是一个基于MVC模型的Web开发框架,重点是分开关注(关注点的分离),即分离业务逻辑,用户界面和输入控制。特定的演示模式类似于Java,因此我不会在此处详细说明。目录结构:
1
2
3
4
5
6
7
8
9
控制器:包含控制器类文件。控制器负责处理用户输入,操作模型并返回视图。
Models:存储应用程序的模型类,该类别定义了应用程序的数据结构和业务逻辑。
views:包含用于渲染用户界面的视图文件(.cshtml或.vbhtml)。通常,每个控制器都有一个相应的视图文件夹。
脚本:存储JavaScript文件。
App_start:包含启动配置文件,例如Routeconfig.cs,Bundleconfig.cs,FilterConfig.cs,等等。
APP_DATA:存储应用程序的数据库文件或其他数据文件。
BIN:存储编译的组件(DLL文件)和依赖项。
Global.asax:处理应用程序级事件的应用程序的全局配置文件。
Web.config:应用程序的配置文件。
2.3. ASP.NET Core Razor Pages
ASP.NET Core是一个跨平台,高性能开源框架,用于构建现代Web应用程序,云应用程序和微服务。它以更好的性能和灵活性集成了ASP.NET MVC和Web API。通过剃须刀提供类似网络形式的开发体验,但更轻。每个页面都由剃须刀文件(.cshtml)和一个代码范围文件(.cshtml.cs)组成,并且页面逻辑与视图紧密集成在一起。避免使用MVC中的路由配置复杂性,适用于小页数的应用程序,用于小型项目或单页应用程序以及您想要简化页面开发的方案。目录结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
控制器:包含控制器类文件。控制器处理请求并返回响应,通常使用API样式或MVC模式。
模型:包含定义应用程序数据结构和业务逻辑的模型类。
View :包含用于渲染用户界面的视图文件(.cshtml)。
共享:包含共享视图,例如布局文件_Layout.cshtml。
第:页用于Razor页面项目,包括页面文件(.cshtml)和页面模型文件(.cshtml.cs)。
wwwroot:存储静态文件(CSS,JavaScript,图像等)。该文件夹中的内容可以直接通过URL访问。
CSS:存储CSS文件。
JS:存储JavaScript文件。
LIB:通过NPM或Libman等包装管理人员安装的前端库存储前端库。
AppSettings.json:应用程序配置文件替换了传统的Web.config。
program.cs:应用程序的输入点,配置并启动应用程序。
startup.cs:为应用程序配置服务和请求管道。通常包括中间件配置和服务依赖注入。
BIN:存储编译的组件(DLL文件)和依赖项。
properties:包含项目的属性文件,例如启动集群。JSON,用于配置开发和发布设置。
3. 反编译工具
在.NET应用程序开发中,预编译是指将应用程序代码的早期编译到库文件中,例如DLL,以提高性能,减少第一个请求的启动时间,并增强代码的保护。预编译通常应用于Web应用程序,例如ASP.NET,其代码可以通过将其预先编译到服务器之前减少或消除运行时编译的需求。当存在此情况时,您需要在/bin目录中对DLL文件进行反复编译以获取源代码。
.NET解码工具有四个选项:DNSPY(2020年左右更新),ILSPY,Dotpeek(由Jetbrains发布)和DNSPYX(非正式更新版本)。
下图是ILSPY解码的结果:

ILSPY对字符串搜索功能不是很友好,因此您可以选择将分解源代码导出到文本中,然后对其进行审核。

如果在分解代码中存在混淆,则可以使用抗膨胀工具来恢复它。目前,有许多反膨胀工具,其中DE4DOT是最主流的反膨胀工具。
检测混淆器类型:
1
de4dot.exe -d c: \ bin \ demo.dll
批处理反吞噬:
1
de4dot.exe -r C: \ Input -RU -RO C: \输出
010-1011
4. 常见漏洞
/webgoat/content/uploadpathmanipulation.aspx.cs
代码的主要目的是将用户上传到服务器上指定目录的文件保存,并在上传成功或失败时向用户显示相应的消息。
特定代码逻辑如下:
页面加载:
page_load方法是空的,什么也没做。当页面加载时,没有特定的逻辑可以执行。
文件上传:
BTNUPLOAD_CLICK方法是按钮点击事件的处理程序,当用户单击上传按钮时会触发。
首先,代码检查FileUpload1控件是否包含文件(即,如果FileUpload1.hasfile为true)。
如果有文件上传,则代码为文件的名称并使用server.mappath将虚拟路径转换为服务器上的物理路径。然后调用fileupload1.saveas将文件保存到指定的路径。
如果文件成功上传,该程序将在标签标签中显示成功消息。
如果在上传期间发生异常,则例外信息将显示在标签标签中。
最后,确保可见标签标签。
典型的文件上传漏洞,未验证文件格式,从而导致攻击者能够上传.aspx文件。
前端代码如下/webgoat/content/uploadpathmanipulation.aspx:

代码审核焦点:
1
2
3
4
saveas()
file.move(sourcePath,destinationPath);
file.copy(sourcePath,destinationPath);
system.io.file.writeallbytes
4.1. 文件上传漏洞
/webgoat/app_code/util.cs
如果CMD参数可控,则可以执行系统命令
代码审核焦点:
1
2
process.start()
Shellexecute()
4.2. RCE 漏洞
/webgoat/content/sqlindoction.aspx.cs
跟进getemailbyname方法

采用参数剪接以导致SQL注入。
代码审核焦点:
1
SQL语句剪接
4.3. SQL 注入漏洞
/webgoat/content/pathmanipulation.aspx.cs
33行文件名是可控的,请跟进响应文件函数:

文件路径未过滤,直接读取文件
将读取文件流写入HTTP响应,从而导致任何文件读取:

代码审核焦点:
1
2
3
opentext和openRead文件对象的方法
filemode.open and filemode.Read FileStream对象
wress.writefile通常用于文件下载
4.4. 任意文件读取/下载
在.NET Web项目中,入口点是程序开始执行的地方,确定应用程序的初始化过程。入口点因项目类型而异,这是一些常见的.NET Web项目类型及其输入点的概述:5. 查找程序入口点
ASP.NET核心项目的输入点通常位于program.cs文件中。该文件包含主要方法,该方法是应用程序的实际输入。例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
公共课程计划
{
公共静态void main(string [] args)
{
CreateHostBuilder(args).build()。run();
}
公共静态iHostBuilder create -hostbuilder(string [] args)=
host.CreatedEdeFaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder=
{
webbuilder.usestartupstartup();
});
}
Main方法:应用程序从这里开始执行。 CreateHostBuilder方法用于创建和配置应用程序的主机。
Startup类:指定在启动期间配置应用程序服务和中间件的类。
5.1. ASP.NET Core 项目
在ASP.NET MVC项目中,输入点在global.asax.cs文件中,通常是application_start方法。例子:
1
2
3
4
5
6
7
8
9
10
公共类MvCapplication : System.Web.httpapplication
{
受保护的void application_start()
{
arearegistration.registerallareas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(Routetable.Routes);
Bundleconfig.RegisterBundles(Bondletable.Bundles);
}
}
Application_Start方法:这是MVC应用程序的入口点。当应用程序启动时,ASP.NET将调用此方法以配置路由,过滤器,束等。
5.2. ASP.NET MVC 项目
ASP.NET Web Forms Project的入口点也位于global.asax.cs文件中,并且也使用application_start方法初始化。例子:
1
2
3
4
5
6
7
公共类Global : System.Web.httpapplication
{
受保护的void application_start(对象发送者,EventArgs e)
{
//应用程序启动时配置代码
}
}
5.3. ASP.NET Web Forms 项目
在.NET Web项目中,路由定义了如何将URL请求映射到特定的控制器和操作方法(或处理程序)。在确定程序入口点和风险不安全的功能之后,如何使用漏洞访问页面? Web表单项目非常简单。只需直接访问相应的xxx.aspx。您需要在其他体系结构下找到其路由定义。6. 查找路由
ASP.NET Core使用启动.cs文件中的配置方法进行配置。通常,您会看到类似于以下的代码:1
2
3
4
5
6
7
8
9
10
11
公共无效配置(iApplicationBuilder应用程序,iHostingenvorlirnment env)
{
app.userouting();
App.UseEndPoints(endpoints=
{
endpoints.mapcontrollerroute(
name:“默认”,
statter:'{controller=home}/{action=index}/{id?}');
});
}
在这里,MapControllerRoute方法定义了默认路由模式,您可以在其中查看和定义项目的所有路由。
6.1. ASP.NET Core 项目
在ASP.NET MVC项目中,路由通常在App_start文件夹中的RouteConfig.cs文件中配置:1
2
3
4
5
6
7
8
9
10
11
12
13
公共类Routeconfig
{
公共静态void registerRoutes(路由集会路线)
{
doutes.ignoreroute('{resource} .axd/{*pathInfo}');
routes.maproute(
name:“默认”,
url3:'{controller}/{action}/{id}',
defaults: new {controller='home',action='index',id=urlparameter.optional}
);
}
}