软件安全测试技术系列|跨站脚本攻击(Cross Sites Script)类漏洞攻击方式与防御措施
本系列文章分享JavaScript语言常见的安全漏洞,漏洞的原理,可能导致的安全问题,以及如何防御与避免。本文分享的是跨站脚本攻击(Cross Sites Script)。
一、漏洞描述
跨站脚本攻击,Cross Site Script(简称 CSS或)。指黑客通过“HTML注入”篡改了网页,插入了恶意的脚本(主要是JavaScript脚本),从而在用户浏览网页时,控制用户浏览器的一种攻击。
二、会造成的后果
挂马
盗取用户Cookie。
钓鱼攻击,高级的钓鱼技巧。
删除目标文章、恶意篡改数据、嫁祸。
劫持用户Web行为,甚至进一步渗透内网。
爆发Web2.0蠕虫。
蠕虫式挂马攻击、刷广告、刷浏量、破坏网上数据
其它安全问题
三、攻击方式
在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
在 onload、onerror、onclick 等事件中,注入不受控制代码。
在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。
在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。
......
四、如何避免
通用建议
1. 验证所有来源的所有输入。验证应使用白名单:仅接受适合指定结构的数据,而不是拒绝不对的模式。检查:
数据类型
大小
范围
格式
预期值
2. 完全编码所有动态数据,然后再将其嵌入网页。编码应该是上下文敏感的。例如:
用于 HTML 内容的 HTML 编码。
用于输出数据到特性值的 HTML 特性编码。
JavaScript 的 JavaScript 编码。
3. 考虑使用 ESAPI4JS 编码库。
具体防御方式
1、HttpOnly
原理:浏览器禁止页面的Javascript访问带有HttpOnly属性的cookie。(实质解决的是:XSS后的cookie劫持攻击)如今已成为一种“标准”的做法。
解决方案:
JavaEE给Cookie添加HttpOnly的方式为:
response.setHeader("Set-Cookie","cookiename=value; Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
2、输入检查(XSS Filter)
原理:让一些基于特殊字符的攻击失效。(常见的Web漏洞如XSS、SQLInjection等,都要求攻击者构造一些特殊字符)
* 输入检查的逻辑,必须在服务端实现,因为客户端的检查也是很容易被攻击者绕过,现有的普遍做法是两端都做同样的检查,客户端的检查可以阻挡大部分误操作的正常用户,从而节约服务器的资源。
解决方案:
检查是否包含"JavaScript","<script></script>"等敏感字符。以及对字符串中的<>:"&/'等特殊字符做处理
3、输出检查
原理:一般来说除了富文本输出之外,在变量输出到HTML页面时,使用编码或转义的方式来防御XSS攻击
解决方案:
* 针对HTML代码的编码方式:HtmlEncode
* PHP:htmlentities()和htmlspecialchars()两个函数
* Javascript:JavascriptEncode(需要使用""对特殊字符进行转义,同时要求输出的变量必须在引号内部)
* 在URL的path(路径)或者search(参数)中输出,使用URLEncode
JavaScript
Data obtained from the execution of an SQL command is rendered to a web-page template
function renderUserProfileTable(res, connection, user_id) { connection.query('SELECT id,name,description from user WHERE id= ?', [user_id],function(err, results) { var table = "<table>" table += "<table class='profile-html-table'>" table += "<tr><td>" + results[0].name + "</td></tr>" table += "<tr><td>" + results[0].description + "</td></tr>" table += "</table>" res.render("profile", table) }); } |
Data obtained from the execution of an SQL command is encoded and then rendered to a web-page template
var htmlencoder = require('htmlencode'); function renderUserProfileTable(res, connection, user_id) { connection.query('SELECT id,name,description from user WHERE id= ?', [user_id],function(err, results) { var table = "<table>" table += "<table class='profile-html-table'>" table += "<tr><td>" + htmlencoder.htmlEncode(results[0].name) + "</td></tr>" table += "<tr><td>" + htmlencoder.htmlEncode(results[0].description) + "</td></tr>" table += "</table>" res.render("profile", table) }); } |
4.更严格的做法
除了数字和字母外的所有字符,都使用十六进制的方式进行编码
后续会继续分享其他的JavaScript语言常见安全漏洞,欢迎关注,了解更多软件测试技术内容。如需不同品牌软件漏洞扫描工具试用或参数比对,也可私信我。
(谢绝转载,更多内容可查看我的专栏)