软件安全性测试(连载8)

简介: 软件安全性测试(连载8)

2.4 HTML5的安全


1. <audio><video>标签


对于<audio>和<video>这两个标签安全性而言,在于它同<img>一样支持跨域请求,比如。


<audioscr="http://www.mydomain.com/del_paper.jsp?id=5">
<video src="#"onerror="http://www.mydomain.com/hello.js">


2.iframe安全性

      对于iframe一直是个前端的安全隐患,比如点击挟持,支持跨域等。维持HTMLiframesandbox中加入了几个安全属性。

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

1allow-scripts

如下HTML语句。

sandbox="allow-scripts"<br>
<iframesrc="frame1.html" sandbox="allow-scripts">
 <p>你的浏览器不支持iframes.</p>
</iframe>
<br>sandbox=""<br>
<iframesrc="frame1.html" sandbox="">
 <p>你的浏览器不支持iframes.</p>
</iframe>


      第一个iframe可以执行src中的脚本,而第二个iframe则不可以执行src中的脚本,因为它没有sandbox="allow-scripts"选项。frame1.html HTML脚本如下。

<!doctype html>
<html>
<head>
<metacharset="gb2312">
<title>iframe1</title>
</head>
<body>
<buttononclick="getDateTime()">获得日期和时间</button>
<divid="dt"></div>
<script>
function getDateTime()
{
var d=new Date();
document.getElementById("dt").innerHTML=d;
}
</script>
</body>
</html>


      18sandbox中有allow-scripts和没有allow-scripts的情形。

image.png

18 sandbox是否具有allow-scripts


2allow-forms

如下HTML语句。

sandbox="allow-forms"<br>
<iframesrc="frame2.html" sandbox="allow-forms">
 <p>你的浏览器不支持iframes.</p>
</iframe>
<br>sandbox=""<br>
<iframesrc="frame2.html" sandbox="">
 <p>你的浏览器不支持iframes.</p>
</iframe>


      第一个iframe可以提交src内的form表单,而第二个iframe则不可以提交src内的form表单,因为它没有sandbox=" allow-forms"选项。frame2.html HTML脚本如下。

<!doctype html>
<html>
<head>
<metacharset="gb2312">
<title>iframe2</title>
</head>
<body>
<formaction="demo_form.jsp">
姓: <input type="text" name="fname"value="Gu"><br><br>
名: <input type="text" name="lname"value="Xiang"><br><br>
<input type="submit"value="提交">
</form>
</body>
</html>

      demo_form.jsp脚本如下。

<!doctype html>
<html>
<head>
<metacharset="gb2312">
<title>ifrme2</title>
</head>
<body>
<%
Stringfname=request.getParameter("fname");  
Stringlname=request.getParameter("lname");  
%>
fname:<%=fname%><br>
lname:<%=lname%>
</body>
</html>


19sandbox中有allow-forms和没有allow-forms的情形。

image.png

19 sandbox是否具有allow-forms


3allow-same-origin

如下HTML语句。

sandbox="allow-same-originallow-scripts"<br>
<iframesrc="frame3.html" sandbox="allow-same-origin allow-scripts">
 <p>你的浏览器不支持iframes.</p>
</iframe>
<br>sandbox=""<br>
<iframesrc="frame3.html" sandbox="">
 <p>你的浏览器不支持iframes.</p>
</iframe>


第一个iframe可以执行src内的Javascript脚本,而第二个iframe则不可以执行src内的Javascript脚本,因为它没有sandbox="allow-same-origin""allow-scripts"选项。frame3.html HTML脚本如下。

 

<!doctype html>
<html>
<head>
<metacharset="gb2312">
<title>ifrme3</title>
</head>
<body>
<p>图书列表(来自通过 JavaScript 取回的 XML 文件):</p>
<script>
if (window.XMLHttpRequest)
 {
 xhttp=new XMLHttpRequest();
 }
else // for IE 5/6
 {
 xhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }
xhttp.open("GET","book.xml",false);
xhttp.send();
xmlDoc=xhttp.responseXML;
x=xmlDoc.getElementsByTagName('title');
for (i=0;i<x.length;i++)
{
document.write(x[i].childNodes[0].nodeValue);
document.write("<br>");
}
</script>
</body>
</html>


      book.xml如下。


<?xml version="1.0"encoding="ISO-8859-1"?>
<bookstore>
<bookcategory="children">
<titlelang="en">Harry Potter</title>
<author>J K.Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<bookcategory="cooking">
<titlelang="en">Everyday Italian</title>
<author>Giada DeLaurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<bookcategory="web" cover="paperback">
<titlelang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
<bookcategory="web">
<titlelang="en">XQuery Kick Start</title>
<author>JamesMcGovern</author>
<author>PerBothner</author>
<author>KurtCagle</author>
<author>JamesLinn</author>
<author>VaidyanathanNagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
</bookstore>


20sandbox中有allow-same-origin和没有allow-same-origin的情形。

image.png

20 sandbox是否具有allow-same-origin


3. a标签的rel="noopener noreferrer" 属性

      a标签的rel="noopenernoreferrer" 属性主要目的是不把父窗口中的信息传给子窗口,从而实现隐私的保密性。主窗口代码如下。

<html>
<body>
<scripttype="text/javascript">
function de(n){
    document.getElementById('a').value= n;
}
</script>
<input type="text"name="a" id="a">
<br><ahref="b.html" target="_blank">不带noopener noreferrer属性</a>
</body>
</html>


      子窗口b.html代码如下。

<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=utf-8" />
<scripttype="text/javascript">
function demo(){
    window.opener.de("JerryGu");
    window.close();
}
</script>
</head>
<body>
</script>
把JerryGu传给父窗口<br>
<inputtype="submit" name="submit" value="submit2"onclick="demo()">
</body>
</html>


      在父窗口中存在一个javascript函数function de(n),当通过点击不带noopener noreferrer属性超链进入到b.html中后,子窗口可以通过window.opener.de("JerryGu");方法调用父窗口的函数从而达到父子窗口通信的功能。但是有时为了保持父节点的隐私性,特别是打开一个异源网站。只需要在主窗口代码不带noopener noreferrer属性中加入rel="noopenernoreferrer" 属性即可:
noopener noreferrer属性。这样通过点击标签a进入b.html后,子窗口将无法与父窗口进行通信。实质上加入了rel="noopenernoreferrer" 属性,在页面传输过程中不含有referrer头信息。


4. Canvas

Canvas中文名字为“画布”,是HTML5的一个重要功能,但是利用它可以破解一些简单的验证码。这里以一个为0-9数字的验证码为例进行介绍。其原理为。

1.获取0-9数字的验证码灰度化后的特征数值。

2.将验证码按数字等宽度拆分。

3.灰度化拆分后的每一个图片。

4.与特征数值进行比较。

5.得到验证码。


其原理见21

image.png

21 通过画布破解验证码步骤


其代码如下。

<html>
<head>
<metahttp-equiv="Content-Type" content="text/html;charset=utf-8">
<title>演示十七:验证码的破解</title>
<scriptlanguage="javascript" type="text/javascript">
function login(){
varimage=document.querySelector(".myimage"); //获取到验证码图片
varcanvas=document.createElement('canvas'); //新建一个canvas
varctx=canvas.getContext("2d");//获取2D上下文
var numbers=[];//存储数字模板的数组
canvas.width = image.width; //设置canvas的宽度
canvas.height = image.height; //设置canvas的高度
document.body.appendChild(canvas);//将canvas添加进文档
ctx.drawImage(image,0,0);//将验证码绘制到canvas上
for (var i=0;i<4;i++) { //循环四次,识别四个数字
varpixels=ctx.getImageData(13*i+7,3,9,16).data; //按照公式获取到每个数字上的像素点
var ldString = "a";//用来存储明暗值的字符串
for (varj=0,length=pixels.length;j<length;j+=4) {//每次循环取四个值,分别是一个像素点的r,g,b,a值
ldString=ldString+(+(pixels[j]*0.3+pixels[j+1]*0.59+pixels[j+2]*0.11>=128)); //灰度化+二值化,但我们并没有真正的处理图像
}                
console.log(ldString); //输出存储着明暗值的字符串
}
}
function display(){
var image =document.querySelector(".myimage");//如果要用在greasemonkey脚本里,可以把下面的代码放在image的onload事件里         
var canvas =document.createElement('canvas');                
var ctx =canvas.getContext("2d");                
var numbers = [//模板,依次是0-9十个数字对应的明暗值字符串
"111000111100000001100111001001111100001111100001111100001111100001111100001111100001111100100111001100000001111000111111111111111111111111111111",
"111000111100000111100000111111100111111100111111100111111100111111100111111100111111100111111100111100000000100000000111111111111111111111111111",
"100000111000000011011111001111111001111111001111110011111100111111001111110011111100111111001111111000000001000000001111111111111111111111111111",
"000011111110011111110011111110111111000111111000111111110011111111011111111011111100011111000111111001111111111111111111111111111111111000000000",
"001110000001110000001110000001110000001110000001110000001110000000010000000010000001110000001110000001110000111110000111110000111110000000000000",
"000011111111111111111111111111111111011111111000111111100011111110011111110011110100011111000111111001111111111111111111111111111111111000000000",
"000001111111101111111111111111111111000111111000001111111001111111100111111100111111000111000001111000011111111111111111111111111111111000000000",
"100000000100000000111111100111111101111111001111110011111110111111100111111101111111001111111001111110011111110011111111111111111111111111111111",
"110000011100000001100111001100111001100011011110000011110000011100110001001111100001111100000111000100000001110000011111111111111111111111111111",
"110000111100000001000111001001111100001111100000111000100000000110000100111111100111111001101111001100000011110000111111111111111111111111111111"];
var captcha = "";//存放识别后的验证码
canvas.width = image.width;
canvas.height = image.height;
document.body.appendChild(canvas);
ctx.drawImage(image, 0, 0);
for (var i = 0; i < 4; i++) {
    var pixels = ctx.getImageData(13 * i + 7,3, 9, 16).data;
    var ldString = "";
    for (var j = 0,length = pixels.length; j< length; j += 4) {
        ldString = ldString + (+(pixels[j] *0.3 + pixels[j + 1] * 0.59 + pixels[j + 2] * 0.11 >= 140));
    }
    var comms = numbers.map(function (value){//为了100%识别率,这里不能直接判断是否和模板字符串相等,因为可能有个别0被计算成1,或者相反
        returnldString.split("").filter(function (v, index) {
            return value[index] === v
        }).length
    });
    captcha +=comms.indexOf(Math.max.apply(null, comms)); //添加到识别好的验证码中
}
//document.querySelector("input[name=validateCode]").value= captcha; //写入目标文本框
alert(captcha);
}
</script>
</head>
<bodyonload="display()">
<img src="1.bmp"class="myimage">
</body>
</html>


5. 获取地理坐标

对于在线地图软件而言,获取本地经纬度值是非常重要的功能,在HTNL5中实现了这个功能。效果如22所示。


image.png

22 获取当前的经纬度


      类似本地经纬度信息属于个人隐私的范畴,软件如果要获取这些信息,应该在使用之前得到用户的许可,特别是在APP端。现在ChromeFireFox都支持了预先通知的机制,见23所示。


image.png

23 预先通知获取用户隐私机制


6. 本地存储

      HTML5本地存储的前身就是cookie,但是cookie每个域尽可存储4K信息,而作为本地存储,每个域竟可存储高达5M信息。关于本地存储需要注意以下几个问题。

  • 从安全性角度而言不可替代cookie
  • 不要存储敏感信息。
  • 防止XSS注入,严格过滤输入输出。
  • 容易遭受跨目录攻击。
  • 容易遭受DNS欺骗攻击。
  • 是恶意代码栖息的温床。
  • 具体细节本书不详细解开,有兴趣的读者可以查阅相关资料。


前面所述的均为前端的安全性,在这里特别需要指出,用户可以通过截包工具,自己写接口代码等方式绕过前端访问后端,所以类似于XSS注入的防御不仅要在前端做好把关,更重要的是在后端进行二次控制。下面从后端的角度来进行讲解WEB的安全性。


星云测试

http://www.teststars.cc

奇林软件

http://www.kylinpet.com

联合通测

http://www.quicktesting.net


目录
相关文章
|
前端开发 JavaScript
软件安全性测试(连载4)
软件安全性测试(连载4)
60 0
|
存储 前端开发 JavaScript
软件安全性测试(连载5)
软件安全性测试(连载5)
143 0
软件安全性测试(连载5)
|
存储 移动开发 算法
软件安全性测试(连载19)
软件安全性测试(连载19)
105 0
软件安全性测试(连载19)
|
存储 JavaScript 前端开发
软件安全性测试(连载3)
软件安全性测试(连载3)
110 0
软件安全性测试(连载3)
|
前端开发 JavaScript 安全
软件安全性测试(连载13)
软件安全性测试(连载13)
155 0
软件安全性测试(连载13)
|
存储 安全 Java
软件安全性测试(连载24)
软件安全性测试(连载24)
125 0
软件安全性测试(连载24)
|
JSON 监控 安全
软件安全性测试(连载2)
软件安全性测试(连载2)
127 0
软件安全性测试(连载2)
|
缓存 安全 Java
软件安全性测试(连载22)
软件安全性测试(连载22)
118 0
软件安全性测试(连载22)
|
安全 程序员 网络安全
软件安全性测试(连载18)
软件安全性测试(连载18)
98 0
软件安全性测试(连载18)
|
SQL 缓存 网络协议
软件安全性测试(连载23)
软件安全性测试(连载23)
122 0
软件安全性测试(连载23)
下一篇
无影云桌面