CVE-2023-36934:MOVEit Transfer SQL注入分析

VSole2023-07-19 09:46:22

背景介绍:

MOVEit Transfer是一种广泛使用的 Web 应用程序,最近由于一系列 SQL 注入 (SQLi) 漏洞而受到密切关注。这些漏洞影响已发布的 MOVEit Transfer 的各个版本。利用该漏洞可能会授予对 MOVEit Transfer 数据库的未经授权的访问,从而允许攻击者操纵和泄露敏感信息。

补丁分析:

反编译了未打补丁和打补丁版本的 DLL 文件,并对反编译的 C# 代码进行了 Git diff,可以方便地比较未修补版本和修补版本之间的差别。


可以注意到 UserEngine::UserProcessPassChangeRequest() 函数发生了变化,该函数可以从Humans.aspx和machine.aspx中调用,经过仔细检查,很明显,如果可以控制 MyLoginName 变量,则很容易受到 SQL 注入攻击。

最初,通过请求中的 Arg01 参数注入Payloads,可能会出现 SQL 注入,然而,MOVEit 通过 SILUtility.XHTMLClean() 函数来降低风险,从而有效防止任何成功利用此 SQLi 漏洞的行为。

有了这种理解,研究人员重点转向寻找一种绕过清理并以未经清理的方式操纵 Arg01 参数的方法,因此了解 MOVEit 软件如何处理请求非常重要。

对于 human.aspx,参数分配是通过 siGlobs.GetIncomingVariables() 进行的,此函数扫描请求并解析可用参数,包括来自表单帖子、查询字符串、多部分表单、通过“ep”参数加密的查询字符串的参数(如果参数先前在会话中设置为变量)。

所有提到的函数调用主要涉及解析提供的参数并通过使用 XHTMLClean() 方法进行清理,然后,清理后的值存储在 siGlobs 对象中。

此过程的最后一步是尝试从数据库检索会话变量,其背后的逻辑如下:如果通过 cookie (ASP.NET_SessionId) 提供会话,后端系统将检查之前是否为此会话设置了任何变量,如果此类变量存在,它们将覆盖当前请求中收到的参数。

随后的过程涉及确定这些变量在数据库中的存储点,在相关功能中, SaveArgumentsToSessionForRedirect() 由于与未经身份验证的操作相关而脱颖而出。

尝试1:

经过一些 grep 和阅读代码后,研究人员偶然发现了一个引起注意的特定代码片段,该代码段从密码变量中设置了 Arg01 的值,在检查代码后,密码没有经过清理,这意味着在这种情况下 Arg01 将被分配一个完全未经清理的值。

siGlobs.FromSignon = "1";siGlobs.Transaction = "msgpassword";siGlobs.Arg01 = siGlobs.Password;siGlobs.Arg02 = text3;siGlobs.Password = "";siGlobs.Arg07 = "";siGlobs.SaveArgumentsToSessionForRedirect();

然而,研究人员遇到了一个复杂的情况,此代码片段还为transaction和 FromSignon 变量赋值,这破坏了预期的代码流,如果提供的transaction参数被值“msgpassword”覆盖,它会阻止执行“passchangerequest”,尽管如此,研究人员仍决定验证此代码是否确实可以为 Arg01 保存未经处理的值并可能触发 SQL 注入,特别是当transaction变量不是在数据库中设置而是通过研究人员的参数值设置时。

为了确认这一点,研究人员设置了 Rider debugger,并手动从会话的数据库中删除了transaction变量,并观察到虽然 Arg01 中现在存在特殊字符,但并未发生对 UserEngine::UserProcessPassChangeRequest() 的函数调用,当从 Arg01 中删除特殊字符时,函数调用可以正常工作,经过几个小时的调试和研究后,研究人员意识到这是一个死胡同,需要探索其它替代方法。

尝试2:

在探索对 UserProcessPassChangeRequest 函数的其它调用时,研究人员在 SILMachine.cs (machine.aspx) 中遇到了对同一函数的另一个调用:

但是,清理过程再次应用于 LoginName 变量...研究人员决定重新访问 git diff 来寻找其它线索,他们有了一个非常有希望的发现——用户名的清理不一致,清理后,调用 UrlDecode(),但它应该在清理过程之前发生,这种不一致的顺序同样会影响 LoginName 变量。

这种清理顺序的不规则性仅在 GetEncryptedQueryParameters() 函数中观察到,这为研究人员创造了一条潜在的路径,可以利用加密参数 ep 在 siGlobs 对象中分配 LoginName 值(URL 解码),同时传递transaction参数(可能通过 POST 参数),因为不允许通过查询(加密或未加密)参数使用transaction

POST /machine.aspx?ep={encrypted{Username=sql%27injection}} HTTP/2Host: 192.168.29.73Accept-Language: en-GB,en-US;q=0.9,en;q=0.8Content-Type: application/x-www-form-urlencodedContent-Length: 29
Transaction=passchangerequest

然而这一方案中研究人员意识到 Machine.aspx 页面不支持加密查询参数,该功能仅限于 human.aspx。

困境:

此时,研究人员有两条可能的路径来探索使用 human.aspx 及其加密参数功能:

1.找到一种方法来设置会话变量,其中包含事务“passchangerequest”并通过加密参数进行未净化的 LoginName 

2.找到一种方法,在不设置transaction的情况下,通过加密参数设置未加密的会话变量LoginName

经过一番研究后,研究人员排除了后一种情况的可能性。

最后尝试:

设置调试器后,研究人员检查了 SaveArgumentsToSessionForRedirect() 函数的每次调用,消除了不符合的选项,在此过程中,一个特定的调用引起了研究人员的注意,它深深地隐藏在一系列 if/switch 语句中,在调试器中仔细检查后,transaction和 LoginName 变量完全按照研究人员的期望设置,然而,在代码中达到这一点时仍然遇到了困难。

try{  string value3 = siGlobs.MyRequest.Cookies["InitialPage"].Value;  siGlobs.objDebug.Log(60, string.Format("{0}: InitialPage cookie found: {1}", "Human_Main", value3));  if (Operators.CompareString(value3, CallingPage, TextCompare: false) == 0)  {    break;  }  string text6 = "";  string text7 = value3.ToLower();  if (Regex.IsMatch(text7, "[a-z0-9]+\\\\.aspx"))  {    if (Operators.CompareString(text7, "certtouser.aspx", TextCompare: false) == 0)    {      if (!SILUtility.StrToBool(siGlobs.FromCertToUser))      {        text6 = MyTarget.Substring(0, MyTarget.LastIndexOf("/") + 1) + value3;      }    }    else    {      text6 = MyTarget.Substring(0, MyTarget.LastIndexOf("/") + 1) + value3;    }    if (Operators.CompareString(text6, "", TextCompare: false) != 0)    {      siGlobs.objDebug.Log(60, string.Format("{0}: Redirecting to {1} due to InitialPage cookie", "Human_Main", value3));      siGlobs.SaveArgumentsToSessionForRedirect();      siGlobs.CleanupVariables();      siGlobs.MyResponse.Redirect(siGlobs.MakeEncryptedURLIfNec(text6));    }  }}

此特定调用要求调用页面以外的值设置 InitialValue cookie,在本例中为 humans.aspx,这正是阻止调用此函数的缺失环节。

发出此请求后,将收到一个会话 ID,最重要的是,该 ID 会将transaction参数设置为“passchangerequest”,并将 LoginName 参数设置为 SQL Payloads,这刚好符合了 SQL 注入漏洞的利用。

现在,剩下的唯一任务是在 machine.aspx 请求中设置会话 cookie 并观察执行情况,在此阶段,研究人员预计会话变量将被成功设置,从而由于注入的 SQL Payloads而导致 SQL 异常错误。

利用这一点,可以进一步在数据库中插入新的活动会话,可以利用 Nuclei 执行这些连续的请求来生成系统管理会话和访问令牌。

你学会了吗?如果觉得还不错的话,欢迎分享给更多感兴趣的人~

sql注入变量
本作品采用《CC 协议》,转载必须注明作者和本文链接
菜鸟入坑代码审计,听说BlueCMS比较合适初学者,特此学习,大佬勿喷 漏洞环境&搭建 本地环境搭建,使用phpstudy集成系统,CMS版本为 访问install目录 下一步,查看数据库文件有没有生成 数据库有数据表显示,安...
自2020年6月以来,Acunetix支持日益流行的API查询语言– GraphQL。为此,您将首先创建一个故意易受攻击的API及其GraphQL定义,然后使用Acunetix对其进行扫描,消除使用Acunetix发现的严重漏洞,并确认已消除了这些漏洞。阶段1:设置测试环境 为了能够进行此练习,在测试之前必须准备一个测试环境。在本练习中,我们将Windows操作系统与开源软件一起使用。
发现漏洞一、环境准备1、在Linux主机上准备一套Xampp:模拟攻防2、在VSCode利用Remote Development进行远程调试3、在Lampp的htdos目录下创建security目录,用于编写服务器PHP代码二、编写Login.html三、编写Login.php"; echo "location.href='welcome.php'";}else{ // echo "login-fail. "; echo "location.href='login.html'";}//关闭数据库mysqli_close?
SQL注入测试
2022-05-09 07:47:24
0x01 等保测评项 GBT 22239-2019《信息安全技术 网络安全等级保护基本要求》中,8.1.4.4安全计算环境—入侵防范项中要求包括: a)应遵循最小安装的原则,仅安装需要的组件和应用程序; b)应关闭不需要的系统服务、默认共享和高危端口; c)应通过设定终端接入方式或网络地址范围对通过网络进行管理的管理终端进行限制; d)应提供数据有效性检验功能,保证通过人机接口输入或通过通
针对DVWA编写一个用于辅助SQL注入的工具
概述在学习SQL注入之前,我们应先了解什么是SQL?原理SQL注入就是当开发人员对用户输入数据的合法性没有判断或过滤不严时,攻击者通过拼接恶意SQL语句诱使解释器在未经适当授权的情况下执行意外命令或访问数据。
下面详细了解sql注入、xss攻击及解决四个方面1. 什么是sql注入????所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。是最原始、最简单的攻击,从有了web2.0就有了sql注入攻击。
利用该漏洞可能会授予对 MOVEit Transfer 数据库的未经授权的访问,从而允许攻击者操纵和泄露敏感信息。变量,则很容易受到 SQL 注入攻击。有了这种理解,研究人员重点转向寻找一种绕过清理并以未经清理的方式操纵 Arg01 参数的方法,因此了解 MOVEit 软件如何处理请求非常重要。由于与未经身份验证的操作相关而脱颖而出。
引子2023-02-23,某站发布了一个关于泛微e-cology9 SQL注入的漏洞通告。如上图所示,根据其说明,受影响的版本范围是<=10.55版本。另外,他们还提到该漏洞无权限要求,并不是后台洞。在开头存在一个SecurityFilter的过滤器,SecurityFilter在初始化时会调用weaver.security.filter.SecurityMain中的initFilterBean方法初始化安全规则。而在weaver.security.rules.ruleImp包中的每个类差不多就是每次打的补丁,此包中的类将被重点关注。所以,缩小范围去补丁包的WEB-INF/myclasses/weaver/security/rules/ruleImp目录寻找。
0x00 前言你见过你的SQL注入方式被WEB容器影响吗?了解一些东西之后回到Include/web_inc.php下继续往下翻一翻代码。发送了一次SELECT查询的SQL语句,携带参数1参数2,我们看一看参数的来源。
VSole
网络安全专家