Web 2.0 的发展为网络用户的互动提供了更多机会。用户通过在论坛发表评论,或是在博客发表留言都可能有意或无意输入一些破坏性的内容,从而造成网页不能正常显示,影响其它用户的使用。XSS 全称为Cross Site Scripting,因为CSS 已经用作样式表的简称,故称为XSS。XSS 是一种常见的网站攻击的方法。其原理是通过在网页的输入框输入一些恶意的内容,www.xuhantao.com,通常是javascript 脚本片段,而这些恶意输入在提交之后并重新读回到客户端时,浏览器会解释执行这些恶意的脚本内容,从而影响网页的正常显示。
本文首先简单介绍开发测试人员如何对Web 应用进行XSS 漏洞测试,如何借助工具绕过客户端javascript 校验输入恶意数据;然后针对使用PHP 语言构建的Web 站点,从在输出端对动态内容进行编码、以及在服务器端对输入进行检测两方面介绍如何避免恶意的XSS 攻击。
对Web 应用进行XSS 漏洞测试
测试路径
对WEB 应用进行XSS 漏洞测试,不能仅仅局限于在WEB 页面输入XSS 攻击字段,然后提交。绕过javascript 的检测,输入XSS 脚本,通常被测试人员忽略。下图为XSS 恶意输入绕过javascript 检测的攻击路径。
图1. XSS 攻击测试路径– 绕过javascript 校验
常见的XSS 输入
测试工具
很多工具可以在浏览器发送Get/Post 请求前将其截取,攻击者可以修改请求中的数据,从而绕过javascript 的检验将恶意数据注入服务器。以下是一些常用的截取HTTP 请求的工具列表。
笔者曾经使用TamperIE 对WEB 应用进行安全性测试。TamperIE 小巧易用,涛涛电脑知识网,能够截取IE 浏览器发送的Get/Post 请求,甚至能绕过SSL 加密。不过TamperIE + IE7 工作不稳定。IE7 提供了对IPV6 的支持,如果你并不计划测试你的Web 应用对IPV6 的支持,建议还是使用TamperIE + IE6 的组合。
如图2所示: TamperIE 绕过客户端浏览器javascript 的校验,在POST 请求提交时将其截取,用户可以任意修改表单输入项name 和message 的值,譬如将message 的值修改为 "<script>alert(“XSS hole!!”);</script>",然后点击”Send altered data” 按钮,将修改后的恶意数据发送给Web 服务器。
图2. 使用TamperIE 截取Post 请求
在输出端对动态内容进行编码
对一个Web 应用而言,其动态内容可能来源于用户输入、后台数据库、硬件状态改变或是网络信息等。动态内容特别是来自用户输入的动态内容很有可能包含恶意数据,从而影响网页的正常显示或是执行恶意脚本。将动态内容安全地显示在浏览器端与动态内容所处的上下文背景有关,譬如动态内容处在HTML 正文、表单元素的属性、或是javascript 代码段中。对于一个基于PHP 语言的Web 应用,当执行 "echo"、"print"、"printf"、"<?=" 等语句时表示正在处理动态内容。本节将首先介绍PHP 提供的库函数htmlspecialchars() 的用法,此函数能将5 个HTML 特殊字符转化为可在网页显示的HTML 实体编码;然后将介绍一些常见背景下的XSS 攻击输入,以及如何在输出端对动态内容进行转义、编码从而避免XSS 攻击。
使用PHP 的htmlspecialchars() 显示HTML 特殊字符
从上文列举的XSS 恶意输入可以看到,这些输入中包含了一些特殊的HTML 字符如"<"、">"。当传送到客户端浏览器显示时,浏览器会解释执行这些HTML 或javascript 代码而不是直接显示这些字符串。< > & “ 等字符在HTML语言中有特殊含义,对于用户输入的特殊字符,如何直接显示在网页中而不是被浏览器当作特殊字符进行解析?
HTML字符实体由& 符号、实体名字或者# 加上实体编号、分号三部分组成。以下为HTML 中一些特殊字符的编码。有的字符实体只有实体编号,没有对应的实体名字,譬如单引号。
表1. 一些HTML 特殊字符的实体编码
显示 实体名字 实体编号
< < <
> > >
& & &
“ " "
‘ N/A '
PHP 提供了 htmlspecialchars() 函数可以将HTML 特殊字符转化成在网页上显示的字符实体编码。这样即使用户输入了各种HTML 标记,在读回到浏览器时,会直接显示这些HTML 标记,而不是解释执行。htmlspecialchars() 函数可以将以下五种HTML 特殊字符转成字符实体编码:
当直接调用 htmlspecialchars($str) 时, & " < > 被转义。
当设置ENT_QUOTES 标记时, 即调用 htmlspecialchars($str, ENT_QUOTES) 时,单引号也被转义。
当设置ENT_NOQUOTES 标记时,单引号和双引号都不会被转义。即调用 htmlspecialchars($str, ENT_NOQUOTES) 时,只有& < > 被转义。
不同背景下的动态内容的XSS 攻击及解决方案
XSS 攻击输入与动态内容所处的代码背景相关,譬如动态内容为表单元素属性的值、位于HTML 正文、或是javascript 代码段中等等。
HTML 标记的属性为动态内容
Web 应用中,"input"、"style"、"color" 等HTML 标记的属性都可能为动态内容,其中"input" 标记的"value" 属性通常为动态内容。
例子1