在Web的开发中,存在一些不合法的脚本或文本会被浏览器执行,这些脚本可能被黑客用于攻击,造成一些安全问题,这其中就包括了跨站脚本攻击(XSS)。本文将从多个方面对XSS测试做详细的阐述。
一、XSS测试简介
XSS测试是指通过构造一些恶意脚本代码并通过数据输入渠道将其注入到网站的页面中,从而实现恶意攻击的测试。XSS测试主要分为三种类型:反射型、存储型与DOM-Based型。其中,反射型与存储型是最为典型的两种,这两种XSS类型占据了百分之八十的攻击场景。DOM-Based型是近年来才出现的XSS类型,攻击场景较少。
以下代码是一个简单的反射型XSS测试案例,该案例将在输入框输入恶意代码后,以弹窗的方式被浏览器执行:
<html> <head> <title>反射型XSS测试</title> </head> <body> <form action="/" method="get"> <input type="text" name="input"> <button type="submit">提交</button> </form> <script> var urlParams = new URLSearchParams(window.location.search); var input = urlParams.get('input'); alert(input); </script> </body> </html>
二、反射型XSS测试
1、测试流程
反射型XSS测试的主要流程如下:
1)分析目标站点页面,确定存在可注入的参数;
2)手动或利用测试工具构建包含恶意脚本的请求,发送至目标站点;
3)查看响应结果,在存在XSS漏洞的情况下,页面将会被恶意脚本劫持,用户无法正常操作。
2、测试案例
以下代码是一个反射型XSS测试案例,该案例将在输入框输入恶意代码后,以弹窗的方式被浏览器执行。此外,在这个案例中还演示了用JavaScript对用户输入进行转义的方法:
<html> <head> <title>反射型XSS测试</title> <script> function escapeHTML(str) { return str.replace(/[<>"']/g, function(match){ return { '<': '<', '>': '>', '&': '&', '"': '"', "'": ''' }[match]; }); } function submitForm() { var input = document.getElementById("input").value; input = escapeHTML(input); document.getElementById("output").innerHTML = input; } </script> </head> <body> <form> <input type="text" id="input"> <button type="button" onclick="submitForm()">提交</button> </form> <div id="output"></div> </body> </html>
三、存储型XSS测试
1、测试流程
存储型XSS测试的主要流程如下:
1)分析目标站点页面,确定存在可注入的参数;
2)手动或利用测试工具构建包含恶意脚本的请求,并将该请求提交至目标站点;
3)攻击者在登录时,将恶意脚本代码存储到数据库中;
4)查看响应结果,在存在XSS漏洞的情况下,恶意脚本将在用户再次进入该页面时被执行。
2、测试案例
以下代码是一个存储型XSS测试案例,该案例将在输入框输入恶意代码后,存储到服务器上。用户再次访问该页面时,存储在服务器上的恶意脚本将被浏览器执行:
<html> <head> <title>存储型XSS测试</title> </head> <body> <form action="/" method="post"> <input type="text" name="input"> <button type="submit">提交</button> </form> <script> var xhr = new XMLHttpRequest(); xhr.open('POST', '/', true); xhr.onload = function () { if (xhr.readyState === 4) { alert(xhr.responseText); } }; var input = prompt("请输入恶意代码:"); xhr.send('input=' + input); </script> </body> </html>
四、防范XSS攻击
1、输入时的处理
对于输入时的处理,通常有两种方法:
1)在后端对输入进行过滤和转义,防止特殊字符被当做代码执行;
2)前端对输入进行转义,在输出时再次转义,防止脚本被执行。
以下是JavaScript中常见的防范XSS攻击的转义方法:
function escapeHTML(str) { return str.replace(/[<>"']/g, function(match){ return { '<': '<', '>': '>', '&': '&', '"': '"', "'": ''' }[match]; }); }
2、输出时的处理
输出时的处理需要保证用户数据不被浏览器解析为代码,以下是一些常见的防范XSS攻击的转义方法:
1)对于HTML,使用HTML实体代替特殊字符;
2)对于CSS,使用CSS实体代替特殊字符;
3)对于JavaScript,使用JSON转义代替特殊字符;
以下是JavaScript中常见的防范XSS攻击的输出转义方法:
function escapeHTML(str) { return str.replace(/[<>"']/g, function(match){ return { '<': '<', '>': '>', '&': '&', '"': '"', "'": ''' }[match]; }); } function escapeJS(str) { return str.replace(/[<>"']/g, function(match){ return { '<': '\\u003c', '>': '\\u003e', '&': '\\u0026', '"': '\\u0022', "'": '\\u0027' }[match]; }); } function escapeCSS(str) { return str.replace(/[<>"']/g, function(match){ return { '<': '\\003c', '>': '\\003e', '&': '\\0026', '"': '\\0022', "'": '\\0027' }[match]; }); }
以上三个函数分别对应了Html、Javascript和CSS三个场景的转义方法。