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

2019-12-23 17:17:18 浏览数 (1)

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一直是个前端的安全隐患,比如点击挟持,支持跨域等。维持HTML在iframe的sandbox中加入了几个安全属性。

lallow-same-origin:允许同源访问。

lallow-top-navigation:允许访问顶层窗口。

lallow-forms:允许提交表单。

lallow-scripts:允许执行脚本。

1)allow-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>

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

18 sandbox是否具有allow-scripts值

2)allow-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>

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

19 sandbox是否具有allow-forms值

3)allow-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>

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

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

4. Canvas

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

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

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

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

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

5.得到验证码。

其原理见21。

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所示。

22 获取当前的经纬度

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

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

6. 本地存储

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

l从安全性角度而言不可替代cookie。

l不要存储敏感信息。

l防止XSS注入,严格过滤输入输出。

l容易遭受跨目录攻击。

l容易遭受DNS欺骗攻击。

l是恶意代码栖息的温床。

l具体细节本书不详细解开,有兴趣的读者可以查阅相关资料。

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

0 人点赞