查看原文
其他

详细分析开源软件项目 Ajax.NET Professional 中的RCE 漏洞(CVE-2021-23758)

代码卫士 2022-05-23

 聚焦源代码安全,网罗国内外最新资讯!

作者:Hans-Martin Münch

编译:代码卫士


2021年秋,MOGWAI LABS 实验室在为客户进行渗透测试过程中发现了开源组件 “Ajax.NET Professional” 中的一个反序列化漏洞 (CVE-2021-23758),如下是对漏洞的详细分析。


Ajax.NET Professional 简介


Ajax.NET Professional 是一个开源软件项目,在二零零几年时非常流行,现在仍然可以找到基于该框架的应用程序。GitHub 官方库对它的描述为,“Ajax.NET Professional (AjaxPro) 是微软 ASP.NET 的首批 AJAX 框架之一。该框架将创建JavaScript 代理类用于客户端上,以调用 web 服务器上的方法,在所有常见 web 浏览器(包括移动设备在内)上具有完整的数据类型支持。返回自己的类、结构、数据集、枚举等等,就如直接在 .NET 中所作的那样。”

“完整的数据类型支持” 和 “自己的类“这类短语总是引起我们的注意,因为它们意味着序列化/反序列化流程非常灵活,随后我们将详细讨论这一问题。


基本面


想要使用 AjaxPro 的ASP.NET 应用程序需要在 web.config 文件中配置 HTTP 句柄。该句柄将接收到导入的客户端请求、反序列化参数,之后调用服务器端上的真实方法。它还充当用于调用 .NET 方法的 JavaScript

1<configuration>2 <system.web>3 <httpHandlers>4 <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/>5 </httpHandlers>6 </system.web>7</configuration>

可从 JavaScript 调用的方法必须标有属性 [AjaxPro.AjaxMethod] 或 [AjaxMethod]。还必须使用 “RegisterTypeForAjax” 注册该类,以便框架能够生成将由客户端(第7行)使用的真正的 JavaScript 代码。

1namespace MyDemo 2{ 3 public class DefaultWebPage 4 { 5 protected void Page_Load(object sender, EventArgs e) 6 { 7 AjaxPro.Utility.RegisterTypeForAjax(typeof(DefaultWebPage)); 8 } 910 [AjaxPro.AjaxMethod]11 public static DateTime GetServerTime()12 {13 return DateTime.Now;14 }15 }16}


这里跳过了将用于调用该方法的所生成的 JavaScript 代码,直接查看已生成的 HTTP 请求:

1POST /ajaxpro/AjaxProTest2.MyDemo,AjaxProTest2.ashx HTTP/2 2Host: localhost:44382 3Content-Length: 2 4X-Ajaxpro-Method: GetServerTime 5Content-Type: text/plain; charset=UTF-8 6User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 7Sec-Ch-Ua-Platform: "Windows" 8Accept: */* 9Referer: https://localhost:44382/MyDemo.aspx10Accept-Encoding: gzip, deflate11Accept-Language: en-US,en;q=0.91213{}


Ajax.NET Professional 使用 HTTP POST 请求调用方法服务器端。虽然目标类是URL 的组成部分,但“X-Ajaxpro-Method” 请求标头指明了被调用的方法。方法参数作为 JSON 编码请求主体通过。


JavaScript 反序列化分析


本分析中使用的是 AJAX.NET Professional 的 commit:

f845e338904de7db6908617a2d33840b1dd8b62b。

用于反序列化 JSON 编码 HTTP 主体的主要类是 “JavaScriptDeserializer”。当反序列化方法参数时就会调用静态的 “DeserializaeFromJson” 方法。该方法具有两个参数:一个是具有序列化对象的 JSON 数据,另外一个是预期的数据类型。反序列化成功时,返回的反序列化对象为:

1string json = "[1,2,3,4,5,6]";2object o = JavaScriptDeserializer.DeserializeFromJson(json, typeof(int[]);3if(o != null)4{5 foreach(int i in (int[])o)6 {7 Response.Write(i.ToString());8 }9}


该 JSON 数据被转换为一个 JavaScriptObject 实例并以于其对象类型为 “Deserialize” 方法被通过。在这个方法中,我们可以看到,JSON 对象可通过 “_type” 键包含类型信息。如果该类型是预期类型的子类,则可以覆写被传递给该反序列化的原始类型:

1public static object Deserialize(IJavaScriptObject o, Type type) 2{ 3 ... 4 // If the IJavaScriptObject is an JavaScriptObject and we have a key 5 // __type we will override the Type that is passed to this method. This 6 // will allow us to use implemented classes where the method will use 7 // only the interface. 8 JavaScriptObject jso = o as JavaScriptObject; 9 if (jso != null && jso.Contains("__type"))10 {11 Type t = Type.GetType(jso["__type"].ToString());12 if (type == null || type.IsAssignableFrom(t))13 type = t;14 }15 ...


真正的反序列化通过如下步骤在 “DeserializeCustomObject” 类中执行:

1、创建预期类的对象实例

2、检索所有公开属性的列表

3、遍历属性清单并检查 JSON 对象中是否包含具有该键的元素。如包含,则该代码试图将 JSON 对象的键分配给该属性。

该方法也用于其它很多 JSON 反序列化中。因此,多数 ysoserial,net 框架的JSON 兼容工具都应该能正常运行。

如下 JSON 编码对象小例子。该对象使用的是研究员  Alvaro Muñoz 和 Oleksandr Mirosh 提出的 “AssemblyInstaller” 小工具。

{"testpropert1" : "I'm just a string","testproperty2":{ "__type":"System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "Path":"file:///C:/exploit/MixedAssembly64_v2.dll" }}


要成功实施利用,攻击者仍然需要处理预期的类型限制。如之前所述,预期类型被传递到反序列化,我们的小工具必须是类型的子类。要绕过这个限制,攻击者有两个选项:

  • 找到具有 [AjaxPro.AjaxMethod] 属性集的方法并以非常通用的类作为参数,理想情况下是 System.Object。

  • 找到在反序列化过程中使用客户端提供的类型信息的类。

有意思的是,Ajax.NET Professional 框架为这两种情况都提供了示例:

AjaxPro.Services.IcartService

AajaxPro 21.10.30.1之前的版本中包含该框架实际不适用的示例类,其中一个就是 “ICartService” 类,它应该演示的是AjaxPro 用作购物车应用程序的用途。该类提供了 “AddItem” 方法,它具有 “AjaxMethod” 属性集并将任意对象当作参数。我们可调用该方法实现远程代码执行:

1namespace AjaxPro.Services 2{ 3 [AjaxNamespace("AjaxPro.Services.Cart")] 4 public abstract class ICartService 5 { 6 /// <summary> 7 /// Adds the item. 8 /// </summary> 9 /// <param name="cartName">Name of the cart.</param>10 /// <param name="item">The item.</param>11 /// <returns></returns>12 [AjaxMethod]13 public abstract bool AddItem(string cartName, object item);1415 /// <summary>16 /// Gets the items.17 /// </summary>18 /// <param name="cartName">Name of the cart.</param>19 /// <returns></returns>20 [AjaxMethod]21 public abstract object[] GetItems(string cartName);22 }23}


仔细阅读久可发现它是一个抽象类,因此我们无法创建该类的真正的实例。不过这也没有关系,因为在类尝试安装前就发生了参数反序列化。

滥用间接的类型转换器

该方法并未由我们发现,而是由 Markus Wulftange 发现的。就在我们还在分析源代码时,他就已经发现了此前提到的 ICartService 漏洞。

Ajax.Pro 中包含很多序列化/反序列化常见 .NET 数据类型如 Data Rows、Hashtables\Exceptions 等隐性的类型转换工具。其中一些转换工具还可滥用于获取代码执行权限。下面将详细分析 “HashtableConverter”类,不过其它类也受影响。

在 .NET 中,Hashtable 类提供了简单的键值对集合,它允许将任意对象增加为键和值。

Hashtable myTable = new Hashtable();
// Add some elements to the hash table. myTable.Add("key", "MOGWAI LABS");

如果 Hashtable 实例由 Ajax.NET Professional 序列化,则每个键值的类型信息必须被存储在 JSON 对象中。例如,如下说明了改框架如何序列化 “myTable” 哈希表。

[ [ "key", "MOGWAI LABS", "System.String", "System.String" ]]


从此时开始,攻击就变得显而易见了。攻击者只需将键或值的类型信息替换为 “System.Object” 并将恶意序列化对象提供为值即可。该payload 可被传递到设置了 AjaxPro.AjaxMethod 属性的任何方法并期望哈希表作为参数即可。


缓解措施


当 MOGWAI LABS 报告了这些问题后,Ajax.NET Professional 的开发者 Michael Schwarz 马不停蹄地推出安全更新。从 v21.11.11.1 版本开始,可反序列化的自定义类型必须通过阻止/允许清单进行配置。

<configuration> <ajaxNet> <ajaxSettings> <jsonDeserializationCustomTypes default="deny"> <allow>MyOwnNamespace.*</allow> </jsonDeserializationCustomTypes> </ajaxSettings> </ajaxNet> ...</configuration>


MOGWAI LABS 强烈建议用户升级至最新版本。Nichael Schwarz 甚至提供了 nugget 包使更新变得容易一些。

如由于某些原因,开发人员无法更新,则应阻止访问 “AjaxPro.Services” 的任意尝试,例如如下更新 web.config:

<rewrite> <globalRules> <rule name="RequestBlockingRule1" patternSyntax="Wildcard" stopProcessing="true"> <match url="*" /> <conditions logicalGrouping="MatchAny"> <add input="{URL}" pattern="*AjaxPro.Services*" /> </conditions> <action type="CustomResponse" statusCode="403" subStatusCode="7" statusReason="Forbidden: Access is denied." statusDescription="You do not have permission to view this directory or page using the credentials that you supplied." /> </rule> </globalRules></rewrite>


开发人员需要考虑的是,这样做仍然允许通过 TypeConverters 的利用但至少拦截了通用的利用情况。







推荐阅读
在线阅读版:《2021中国软件供应链安全分析报告》全文白宫和科技巨头在开源软件安全峰会上说了啥?
SAP 严重漏洞可导致供应链攻击Apache PLC4X开发者向企业下最后通牒:如不提供资助将停止支持
Apache 软件基金会:顶级项目仍使用老旧软件,补丁作用被削弱
美国商务部发布软件物料清单 (SBOM) 的最小元素(上)
美国商务部发布软件物料清单 (SBOM) 的最小元素(中)
美国商务部发布软件物料清单 (SBOM) 的最小元素(下)
NIST 发布关于使用“行政令-关键软件”的安全措施指南
NIST 按行政令关于加强软件供应链安全的要求,给出“关键软件”的定义及所含11类软件SolarWinds 攻击者再次发动供应链攻击
美国“加强软件供应链安全实践的指南” (SSDF V1.1草案) 解读来了
软件供应链安全现状分析与对策建议
“木马源”攻击影响多数编程语言的编译器,将在软件供应链攻击中发挥巨大作用GitHub 在 “tar” 和 npm CLI 中发现7个高危的代码执行漏洞
流行的 NPM 包依赖关系中存在远程代码执行缺陷
速修复!热门npm 库 netmask 被曝严重的软件供应链漏洞,已存在9年
Npm 恶意包试图窃取 Discord 敏感信息和浏览器文件
微软“照片”应用Raw 格式图像编码器漏洞 (CVE-2021-24091)的技术分析SolarWinds 供应链事件后,美国考虑实施软件安全评级和标准机制
找到软件供应链的薄弱链条
GitHub谈软件供应链安全及其重要性
揭秘新的供应链攻击:一研究员靠它成功入侵微软、苹果等 35 家科技公司开源软件漏洞安全风险分析
开源OS FreeBSD 中 ftpd chroot 本地提权漏洞 (CVE-2020-7468) 的技术分析
集结30+漏洞 exploit,Gitpaste-12 蠕虫影响 Linux 和开源组件等限时赠书|《软件供应链安全—源代码缺陷实例剖析》新书上市
热门开源CI/CD解决方案 GoCD 中曝极严重漏洞,可被用于接管服务器并执行任意代码
GitKraken漏洞可用于盗取源代码,四大代码托管平台撤销SSH密钥
因服务器配置不当,热门直播平台 Twitch 的125GB 数据和源代码被泄露
彪马PUMA源代码被盗,称客户数据不受影响




原文链接

https://mogwailabs.de/en/blog/2022/01/vulnerability-spotlight-rce-in-ajax.net-professional/


题图:Pixabay License



本文由奇安信编译,不代表奇安信观点。转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。




奇安信代码卫士 (codesafe)

国内首个专注于软件开发安全的产品线。

    觉得不错,就点个 “在看” 或 "赞” 吧~



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存