前言:
本文形成于学习Net代码审计的过程中,记录了环境搭建过程中遇到的坑以及跟进代码过程中的一些迷惑并通过查阅相关文章来进行学习。如有不足之处,还请各位大师傅海涵。
1、.NET基本架构
1.1、基本构成
可支持语言,CLS,模板框架,基本模板,基本操作,基本类库,公共需要运行时,CTS和CLS,OS等;
1.2、可支持语言
.NET框架可支持vb.net,c++,c#,F#,js等语言开发(主要vb.net,c++)
1.3、文件类型
.net可以用C#,VB.NET,Jscrptnet等等来开发,但是通常首选都是C#和VB.NET审计asp.net的时候。
一般来说,在asp.net应用中,需要进行观的文件有:.aspx,.cs,.ashx,dll文件
1、.aspx:动态网页代码(aspx文件是微软的在通过IIS解析执行后的动态网页文件,而不像静态的html文件)服务器端的动作就是在.cs定义的
2、.cs:就是C#语言源代码文件,是后台代码文件,也可以称为类(cs源文件会被转换成dll文件,保护源代码,并可对外开放接口,供他人使用)
3、.ashx:一般处理程序(HttpHandler)是·NET众多web组件的一种,ashx是其扩展名。主要用于写web handler,可以理解成不会显示的aspx页面
4、.dll:cs文件编译之后的程序集(是一个包含可由多个程序,同时使用的代码和数据的库)
1.4、指向解析
在 ASP.NET 中使用代码隐藏方法来设计Web 窗体,可使页代码能够更清晰地从 HTML 内容中分离到完全单独的文件中。
以Login.aspx文件为例
@page 指令如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="Book.Login" %>
其中有三个属性(Inherits、CodeFile、Codebehind)
说明如下:
Inherits:定义供页继承的代码()隐藏类。 它可以是从 Page 类派生的任何类。 此特性与 CodeFile 特性一起使用,后者包含指向代码隐藏类的源文件的路径。 Inherits 特性在使用 C# 作为页面语言时区分大小写,而在使用 Visual Basic 作为页面语言时不区分大小写。如果 Inherits 特性不包含命名空间,ASP.NET 将检查 ClassName 特性是否包含命名空间。 如果包含,ASP.NET 将尝试使用 ClassName 特性的命名空间加载 Inherits 特性中引用的类。 (这假定 Inherits 特性和 ClassName 特性使用同一命名空间。)Inherits 属性用于定义当前 Web 窗体所继承的代码隐藏类(该类是 System.Web.UI.Page 的派生类)。这个 inherits 属性只用于采用代码隐藏方式编写的 Web 窗体,也就是,如果你的代码全都是在 Web 窗体的标签中,就不必用这个属性了。
CodeFile:指定指向页引用的代码隐藏文件的路径。 此特性与 Inherits 特性一起使用,用于将代码隐藏源文件与网页相关联。 此特性仅对编译的页有效。
此特性用于网站项目。
Codebehind:指定包含与页关联的类的已编译文件的名称。 该特性不能在运行时使用。此特性用于 Web 应用程序项目。
Codebehind 属性并不是一个真正的 ASP.NET 属性,在ASP.NET 文档中是找不到它的。
它其实只是一个 Visual Studio .NET 属性,
Visual Studio .NET 就是借用这个属性来很好地跟踪管理项目中的 Web 窗体和与之相对的代码隐藏文件,
比如当你在设计环境中往 Web 窗体上放入一个服务器控件时,
Visual Studio .NET 将自动找到与该 Web 窗体相对应的代码隐藏文件,并自动插入相关的代码
1、Inherits
解释:定义供页继承的代码隐藏类。 它可以是从 Page 类派生的任何类。
此特性与 CodeFile 特性一起使用,后者包含指向代码隐藏类的源文件的路径。
Inherits 特性在使用 C# 作为页面语言时区分大小写,而在使用 Visual Basic 作为页面语言时不区分大小写。
2、CodeFile
解释:指定指向页引用的代码隐藏文件的路径。
此特性与 Inherits 特性一起使用,用于将代码隐藏源文件与网页相关联。 此特性仅对编译的页有效。
3、Codebehind
解释:指定包含与页关联的类的已编译文件的名称。
该特性不能在运行时使用。此特性用于 Web 应用程序项目。
以AddLeaveData.aspx文件举例:
aspx文件主要为html代码
Inherits指向类文件位置
其中Codebehind指向该页面的核心源码位置,
2、反编译工具
2.1、ILSpy
下载地址:https://github.com/icsharpcode/ILSpy/releases
2.2、dnspy
下载地址:https://github.com/dnSpy/dnSpy/releases
2.3、ReFlector
以ILSpy工具为例
打开ILSpy
以Leava_Detail.aspx为例,Inherits="Appleave.AppLeave.AppLeaveView"
找到dll文件,进行反编译Appform.dll
反编译之后找到Appleave.AppLeave.AppLeaveVie,并发现id参数
保存反编译的源码
3、审计思路
3.1、功能点追踪
黑盒寻找到功能点
分析请求的URL所对应源码的路由(抓包分析)
再分析对应的Inherits、CodeFile、CodeBehind(即所指向的程序集,以及路径等信息。找到后反编译后再进行分析)
再对程序进行分析是否可以利用
3.2、功能函数
根据平时收集的功能函数,丢审计工具里面去搜
源码多用几个工具打开,有的工具可能搜不到;函数开始平时日积月累的收集,也可以多查找几个相关功能的源代码,
找出这个功能的所有源代码里面相同的函数,可能就是这个功能函数了
3.3、目录扫描
将源码的所有目录复制下来,搭建好本地环境,然后使用bp挨个跑一遍
3.4、安全模块未引用
为了节省开发成本与时间,很多功能都是基于模块开发,最后耦合在一起的,防护模块也不例外
当某些页面为调用一些安全验证模块,就会出现对应的安全问题
在源码中寻找未调用安全模块的目录(可以使用排除法,
搜索安全模块的函数,然后会出现包含安全模块的目录,将包含安全模块的目录进行排除)
4、漏洞审计
4.1、SQL注入
使用SQL Server Profiler数据库监控审计
当对数据进行请求之后,可监控到
在其中找到带id参数的sql语句
select *, dbo.GetLeaveText(apptext,0) as LeaveText from appform_leavelists where id=3
随后,打开前面反编译的dll文件
通过Leave_Detail.aspx文件查看Appleave.AppLeave.AppLeaveView的cs文件
结合前面监控到的关键字,查找的sql语句.
isen = LngHelper.IsEn是判断cookie是否存在
查看方法Instance.ExeDataSet(text)
方法用法如下:
执行之后发现不存在sql注入,因此可以判断使用了Instance.ExeDataSet方法的都不存在注入
在AddLeaveData.cs发现新的sql语句
调用了sqlCommand.ExecuteScalar()
进入sqlCommand.ExecuteScalar()
发现关键方法RunExecuteReader
访问
http://8.210.121.250:99/appform/AddLeaveData.aspx
在username处输入单引号
and 1=(select is_srvrolemember('sysadmin'))
4.2、Ueditor编辑器文件上传
1、环境搭建
右键 网站-添加网站,选择下载的Ueditor日录, 选择版本为 4.0 的应用程序池
搭建成功
代码要求以应用程序的形式来运行(可以方便加入库依赖和组织代码)。
所以需要把,net 目录转换为应用程序;
传递身份验证选择特定用户
点击连接为,设置特定用户,该特定用户为主机,上存在的用户例如administrator
访问/net/controller.ashx出现如下图所示,说明安装成功
2、漏洞分析
在controller.ashx文件的第十四行接收了action参数
后端根据action值进行方法调用。
当action=uploadimage时,
AllowExtensions:允许上传的文件扩展名列表,通过调用Config.GetStringList("imageAllowFiles")获取。
PathFormat:上传文件的路径格式,通过调用Config.GetString("imagePathFormat")获取。
SizeLimit:上传文件的最大大小限制,通过调用Config.GetInt("imageMaxSize")获取。
UploadFieldName:上传文件的字段名称,通过调用Config.GetString("imageFieldName")获取。
config内容如下:
通过UploadConfig.Base64判断文件是否经过base64加密
如果未加密则通过Request.Files[]获取文件名与文件内容,
中途由CheckFileType()函数判断文件类型是否符合上传条件
跟进CheckFileType.
使用Contains方法检查fileExtension文件名是否符合条件UploadConfig.AllowExtensions
而UploadConfig.AllowExtensions为白名单控制,因此不存在文件上传
当action=catchimage时,调用CrawlerHandler()方法
CrawlerHandler()方法中19行接受source参数
source的值不等于空的时候执行下面语句
Crawlers = Sources.Select(x => new Crawler(x, Server).Fetch()).ToArray();
查看Fetch()方法,用途请看注释
response.ContentType.IndexOf() 是一个字符串方法,用于查找指定子字符串在当前字符串中的位置。
如果找到子字符串,则返回其第一次出现的位置的索引;否则返回-1。
例如,假设 response.ContentType 是 "text/html",
那么 response.ContentType.IndexOf("image") 将返回 -1,因为 "image" 不在 "text/html" 中。
其中catcherPathFormat配置如下:
在Fetch()方法中用Path.GetFileName()获取文件名,ContentType.IndexOf判断文件类型
Path.GetFileName()方法用于从文件路径中提取文件名,以.符号为特征
例如:
制作图片马
copy 1.jpg /b + 1.aspx /a aspxas.jpg
上传
http://8.210.121.1/shell.png?.aspx
上传成功
4.3、HDHCMS未授权
1、环境搭建
在服务器上根据需要新建空白数据库,并设置好访问此数据库的用户名与密码。
配置hdhapp.config文件
找到网站目录的目录下的“hdhapp.config”文件,打开后如果是连“ACCESS”数据库的网点,请把“HdhCmsDataType”的值改成2,如果是连“MSSQL”数据库的网站,请把“HdhCmsDataType”的值改成1。对应的“HdhCmsAccessName”保存ACCESS数据库文件的当前路径及文件名;“HdhCmsConnStr”保存的是MSSQL数据库的当前路径及文件名。
搭建成功
2、漏洞分析
反编译之后,打开源码,查看login.aspx与default.aspx
找到其对应的cs文件login.aspx.cs与Default.aspx.cs
admin.login.cs如下:
通过判断this.DonforKenbest来跳转,当DonforKenbest == "outsite"时跳转至登陆界面
进入HdhCmsFun.cs中查看FunRequestGet()方法
该方法用来获取DonforDdm的值
那么结合前面的判断,使DonforDdm不等于outsite即可进入下一步
HdhGetSub.SubRunValue();
其相关作用如下:
似乎并未看见与default.aspx相关
HdhGetFun.FunAdminLoginTo()方法中存在SQL语句
select Count(admin) from HdhAllVar.SjkQz(),DonforGlcy where admin= DonforYhm
因此需要让admin= DonforYhm为1
DonforYhm由语句中得来,跟进FunGetCookies
string DonforYhm = HdhCmsFun.FunGetCookies(HdhAllVar.CokAdminSet, HdhAllVar.CokAdminUse);
1、先检查是否存在名为CookName的Cookie
2、从名为CookName的Cookie中获取键为CookKey的值,并将其赋给CookValue变量。并返回CookValue
跟进FunGetCookies(HdhAllVar.CokAdminSet, HdhAllVar.CokAdminUse)参数如下:
即CokAdminSet=AdminCook,CokAdminUse=AdminUser
即FunGetCookies(AdminCook,AdminUser)
构造AdminCook=AdminUser=admin访问/admin/Hdhadmin.aspx?DonforKenbest=gly