HTML 5 安全

新标签的XSS

HTML5 定义了很多新的标签、事件,这有可能带来新的XSS攻击。

一些XSS Filter 如果建立了一个黑名单的话,则可能就不会覆盖到HTML5新增的标签和功能,从而避免发生XSS。

笔者曾经在百度空间做过一次测试,使用的是HTML5新增的<video>标签,这个标签可以在网页中远程加载一段视频。与<video>标签类似的还有<audio>标签,用于远程加载一段音频。

<video src="http://tinyvid.tiv/file/29d6d90ad.ogg"
onloadedmetadata="alert(document.cookie);" ondurationchanged="alert(//XSS2/);"
ontimeupdate="alert(/XSS1/);" tabindex="0"></video>

成功地绕过了百度空间的XSS Filter:

HTML 5 中新增的一些标签和属性,使得XSS等Web攻击产生了新的变化,为了总结这些变化,有安全研究者建立了一个HTML 5 Security Cheatsheet 项目,此项目对研究HTML 5 安全有着重要作用。

 

iframe 的 sandbox

<iframe> 标签一直以来都为人所诟病。挂马、XSS、ClickJacking等攻击中都能看到它不光彩的身影。浏览器厂商也一直在想办法限制iframe执行脚本的权限,比如跨窗口访问会有限制,以及IE中的 <iframe> 标签支持 security 属性限制脚本的执行,都在向着这一目标努力。

在HTML5中,专门为iframe 定义了一个新的属性,叫 sandbox。使用 sandbox 这个属性后,<iframe> 标签加载的内容将为视为一个独立的“源”,其中的脚本将被禁止执行,表单被禁止提交,插件被禁止加载,指向其他浏览对象的连接也会被禁止。sandbox 属性可以通过参数来支持更精确的控制。有以下几个值可以选择:

  • allow-same-origin:允许同源访问;
  • allow-top-navigation:允许访问顶层窗口;
  • allow-form:允许提交表单;
  • allow-script:允许执行脚本。

可有的行为即便是设置了allow-scripts,也是不允许的,比如“弹出窗口”。

一个iframe的实例如下:

<iframe sandbox="allow-same-origin allow-forms allow-scripts" 
        src="http://maps.example.com/embedded.html"></iframe>

毫无疑问,iframe的sandbox属性将极大地增强应用使用iframe的安全性。

 

Link Types:noreferrer

在HTML 5 中为<a>标签和<area>标签定义了一个新的Link Types:noreferrer。

标签指定了 noreferrer 后,浏览器在请求该标签指定的地址时将不再发送Referrer。这个标签需要开发者手动添加到页面的标签中,对于有需要的标签可以使用noreferrer。

<a href="xxx" rel="noreferrer" >test</a>

这种设计是出于保护敏感信息和隐私的考虑。因为通过Referrer,可能会泄露一些敏感信息。

 

Cross-Origin Resource Sharing

浏览器实现的同源策略(Same Origin Policy)限制了脚本的跨域请求。但是互联网的发展趋势是越来越开放的,因此跨域访问的需求也变得越来越迫切。同源策略给Web开发者带来了很多困扰,他们不得不设法实现一些“合法”的跨域技术,由此诞生了jsop,iframe跨域等技巧。

W3C委员会决定制定一个新的标准--- CORS 来解决日益迫切的跨域访问问题。

假设从 http://www.a.com/test.html 发起一个跨域的XMLHttpRequest 请求,请求的地址为:http://www.b.com/test.php。

<script>
    var client = new XMLHttpRequest();
    client.open("GET", "http://www.b.com/test.php");
    client.onreadystatechange = function(){ }
    client.send(null);
</script>

如果服务器www.b.com返回一个HTTP Header:

Access-Control-Allow-Origin: http://www.a.com

代码如下:

<?php
header("Access-Control-Allow-Origin: *");
?>
Cross Domain Request Test!

那么这个来自 http://www.a.com/test.html 的跨域请求就会被通过。

在这个过程中,http://www.a.com/test.html 发起的请求还必须带上一个 Origin Header:

Origin: http://www.a.com

在Firefox上,可以找包分析这个过程。

Origin Header 用于标记 HTTP 发起的”源“,服务器端通过识别浏览器自动带上的这个Origin Header,来判断浏览器的请求是否来自一个合法的”源“。Origin Header 可以用于防范CSRF,它不像Referer那么容易被伪造或清空。

在上面的例子中,服务器返回:

Access-Control-Allow-Origin: *

从客户端的跨域请求通过。在这里使用了通配符 "*",这是极其危险的,它将允许来自任意域的请求访问成功。这就好像Flash策略中的 allow-access-from: * 一样,等于没有做任何安全限制。

对于这个跨域访问的标准,还有很多HTTP Header 可以用于进行更精确的控制:

 

PostMessage 跨窗口传递消息

在”跨站脚本攻击“中,曾经提到利用window.name 来跨窗口、跨域传递消息。实际上,window这个对象几乎是不受同源策略限制的,很多脚本攻击都巧妙地利用了window对象的这一特点。

在HTML5中,为了丰富Web开发者的能力,制定了一个新的API:postMessage。postMessage 允许每一个window(包括当前窗口、弹出窗口、iframes等)对象往其他的窗口发送文本消息,从而实现跨窗口的消息传递。这个功能不受同源策略限制的。

下面示例是一个postMessage的用法,

发送窗口:

<iframe src="http://dev.jquery.com/~john/message" id="iframe"></iframe>
<form id="form">
    <input type="text" id="msg" value="Message to send"/>
    <input type="submit"/>
</form>
<script>
window.onload = function(){
    var win = document.getElementById("iframe").contentWindow;
    document.getElementById("form").onsubmit = function(e){
        win.postMessage(document.getElementById("msg").value);
        e.preventDefault();
    };
};
</script> 

接收窗口:

<b>This iframe is loacated on dev.jquery.com</b>
<div id="test">Send me a message!</div>
<script>
document.addEventListener("message", function(e){
    document.getElementById("test").textContent = e.domain + " said: " + e.data;
}, false);
</script>

在这个例子中,发送窗口负责发送消息;而在接收窗口中,需要绑定一个message事件,监听其他窗口发来的消息。这是两个窗口之间的一个”约定“,如果没有监听这个事件,则无法接收到消息。

在使用postMessage()时,有两个安全问题需要注意。

(1)在必要时,可以在接收窗口验证Domain,甚至验证URL,以防来自非法页面的消息。这实际上是在代码中实现一次同源策略的验证过程。

(2)在本例中,接收消息写入textContent,但实际应用中,如果将消息写入innerHTML,甚至直接写入script中,则可能会导致DOM based XSS的产生。根据”Secure By Default“原则,在接收窗口不应该信任接收到的消息,而需要对消息进行安全检查。

使用postMessage,也会使XSS payload变得更加的灵活。Gareth Heyes 曾经实现过一个JavaScript运行环境的sandbox,其原理是创建一个iframe,将JavaScript限制于其中执行。但笔者进过研究发现,利用postMessage()给父窗口发送消息,可以突破此sandbox。

 

Web Storage

过去在浏览器里能够存储信息的方法有以下几种:

  • Cookie
  • Flash Shared Object
  • IE UserData

其中,Cookie主要用于保存登录凭证和少量信息,其最大长度的限制决定了不可能在Cookie中存储太多信息。而Flash Shared Object和IE UserData 则是Adobe与微软自己的功能,并未成为一个通用化的标准。因此W3C委员会希望能在客户端有一个较为强大和方便的本地存储功能,这就是Web Storage。

Web Storage 分为 Session Storage 和 Local Storage。Session Storage 关闭浏览器就会失效,而Local Storage则会一直存在。Web Storage就像一个非关系型数据库,有Key-Value对组成,可以通过JavaScript对其进行操作。使用方法如下:

  • 设置一个值:window.sessionStorage.setItem(key, value);
  • 读取一个值:window.sessionStorage.getItem(key);

下面这个示例展示了 Web Storage 的使用。

<div id="sessionStorage_show">
    sessionStorage Value:
</div>
<br>
<div id="localStorage_show">
    localStorage Value:
</div>

<input id="set" type="button" value="check" onclick="set();">

<script>
function set(){
    window.sessionStorage.setItem("test", "this is sessionStorage");
    if (window.globalStorage){
        window.globalStorage.namedItem("a.com").setItem("test", "this is LocalStorage");
    }else{
        window.localStorage.setItem("test", "this is LocalStorage");
    }

    document.getElementById("sessionStorage_show").innerHTML += window.sessionStorage.getItem("test");
    if(window.globalStorage){
        document.getElementById("localStorage_show").innerHTML += window.glabolStorage.namedItem("a.com").getItem("test");
    }else{
        document.getElementById("localStorage_show").innerHTML += window.localStorage.getItem("test");
    }
}
set();
</script>

运行结果如下:

Web Storage 也受到同源策略的约束,每个域所拥有的信息只会保存在自己的域下,如下例:

<body>
<script>
if (document.domain == "www.a.com"){
    window.localStorage.setItem("test",123);
}
alert(window.localStorage.getItem("test"));
</script>
</body>

运行结果如下:

当域变化时,结果如下:

Web Storage让Web开发更加的灵活多变,它的强大功能也为XSS Payload大开方便之门。攻击者可能将恶意代码保存在Web Storage中,从而实现跨页面攻击。当Web Storage中保存有敏感信息时,也可能成为攻击的目标,而XSS攻击可以完成这一过程。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值