Web应用进行XSS漏洞测试

本文介绍XSS攻击原理及防御措施,包括绕过客户端验证的方法、使用工具如TamperIE进行测试,以及在不同代码上下文中如何正确编码动态内容。
对 WEB 应用进行 XSS 漏洞测试,不能仅仅局限于在 WEB 页面输入 XSS 攻击字段,然后提交。绕过 JavaScript 的检测,输入 XSS 脚本,通常被测试人员忽略。下图为 XSS 恶意输入绕过 JavaScript 检

  对 WEB 应用进行 XSS 漏洞测试,不能仅仅局限于在 WEB 页面输入 XSS 攻击字段,然后提交。绕过 JavaScript 的检测,输入 XSS 脚本,通常被测试人员忽略。下图为 XSS 恶意输入绕过 JavaScript 检测的攻击路径。

  常见的 XSS 输入

  XSS 输入通常包含 JavaScript 脚本,如弹出恶意警告框:<script>alert("XSS");</script>

  XSS 输入也可能是 HTML 代码段,譬如:

  网页不停地刷新 <meta http-equiv="refresh" content="0;">

  嵌入其它网站的链接 <iframe src=http://xxxx width=250 height=250></iframe>

  XSS (Cross Site Scripting) Cheat Sheet 维护了一份常见的 XSS 攻击脚本列表,可用来作为检测 WEB 应用是否存在 XSS 漏洞的测试用例输入。初次接触 XSS 攻击的开发人员可能会对列表提供的一些 XSS 输入不是很理解,本文第二部分将会针对不同代码上下文的 XSS 输入作进一步的解释。

  测试工具

  很多工具可以在浏览器发送 Get/Post 请求前将其截取,攻击者可以修改请求中的数据,从而绕过 JavaScript 的检验将恶意数据注入服务器。以下是一些常用的截取 HTTP 请求的工具列表。

Paros proxy (http://www.parosproxy.org)
Fiddler (http://www.fiddlertool.com/fiddler)
Burp proxy (http://www.portswigger.net/proxy/)
TamperIE (http://www.bayden.com/dl/TamperIESetup.exe)

  笔者曾经使用 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 中一些特殊字符的编码。有的字符实体只有实体编号,没有对应的实体名字,譬如单引号。

  PHP 提供了htmlspecialchars()函数可以将 HTML 特殊字符转化成在网页上显示的字符实体编码。这样即使用户输入了各种 HTML 标记,在读回到浏览器时,会直接显示这些 HTML 标记,而不是解释执行。htmlspecialchars()函数可以将以下五种 HTML 特殊字符转成字符实体编码:

amp; 转成 amp;amp; 转成 amp;quot;lt; 转成 amp;lt;gt; 转成 amp;gt; 转成 amp;#39; 当直接调用 htmlspecialchars($str)时, 被转义。 当设置 ENT_QUOTES 标记时, 即调用htmlspecialch

&amp; 转成 &amp;amp;
“ 转成 &amp;quot;
&lt; 转成 &amp;lt;
&gt; 转成 &amp;gt;
‘ 转成 &amp;#39;

  当直接调用 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

&lt;form…&gt;&lt;INPUT type=text name="msg" id="msg" size=10 maxlength=8 value="&lt;?= $msg?&gt;"&gt;&lt;/form&gt;

  攻击XSS输入

Hello"&gt;&lt;script&gt;evil_script()&lt;/script&gt;

  将动态内容替换

  将 $msg 替换为恶意 XSS 输入:

&lt;form…&gt;&lt;INPUT type=text name="msg" id="msg" size=10 maxlength=8 
value="Hello"&gt;&lt;script&gt;evil_script()&lt;/script&gt;"&gt;&lt;/form&gt;

  例子2

&lt;form…&gt;&lt;INPUT type=text name="msg" id="msg" size=10 maxlength=8 value=&lt;?= $msg?&gt;&gt;&lt;/form&gt;

  攻击 XSS 输入

Hello onmouseover=evil_script()

  将动态内容替换

  将 $msg 替换为恶意 XSS 输入:

&lt;form…&gt;&lt;INPUT type=text name="msg" id="msg" size=10 maxlength=8 
value=Hello onmouseover=evil_script()&gt;&lt;/form&gt;

  分析

  从例子 1 可以看到其 XSS攻击输入中包含了 HTML 特殊字符 < > "

  从例子 2 可以看到其 XSS 攻击输入中没有包含上节中提到的五种 HTML 字符, 但是 "value"属性值没有使用双引号包围。

  解决方案

  调用htmlspecialchars($str, ENT_QUOTES)将以下 5 种 HTML 特殊字符 < > &‘ “ 转义;同时使属性值被双引号包围。譬如:

&lt;form…&gt;&lt;INPUT type=text name="msg" id="msg" size=10 maxlength=8 
value="&lt;?= htmlspecialchars($msg, ENT_QUOTES))?&gt;"&gt;&lt;/form&gt;

  注意事项

  将 input 的 value 进行转义,必须考虑显示和存储数据的一致性问题,即显示在浏览器端和存储在服务器端后台的数据可能因为转义而变得不一致。譬如存储在服务器端的后台原始数据包含了以上 5 种特殊字符,但是没有转义,为了防止 XSS 攻击,在浏览器端输出时对 HTML 特殊字符进行了转义:

1. 当再度将表单提交时,存储的内容将会变成转义后的值。 2. 当使用 JavaScript 操作表单元素,需要使用到表单元素的值时,必须考虑到值可能已经被转义

  1. 当再度将表单提交时,存储的内容将会变成转义后的值。

  2. 当使用 JavaScript 操作表单元素,需要使用到表单元素的值时,必须考虑到值可能已经被转义。

  HTML文本为动态内容

  例子

&lt;b&gt; 欢迎:&lt;?= $welcome_msg?&gt;&lt;/b&gt;
攻击XSS输入
&lt;script&gt;evil_script()&lt;/script&gt;
将动态内容替换
将$welcome_msg 替换为恶意 XSS 输入:
&lt;b&gt;欢迎:&lt;script&gt;evil_script()&lt;/script&gt;&lt;/b&gt;

  分析

  在 HTML 正文背景下,< > 字符会引入 HTML 标记,& 可能会认为字符实体编码的开始,所以需要将 < > & 转义

  解决方案

  为简洁起见,直接使用 htmlspecialchars()将 5 种 HTML 特殊字符转义,如:

&lt;b&gt;欢迎:&lt;?= htmlspecialchars($welcome_msg,, ENT_NOQUOTES)?&gt;&lt;/b&gt;

  URL的值为动态内容

  Script/Style/Img/ActiveX/Applet/Frameset… 等标记的 src 或 href 属性如果为动态内容,必须确保这些 URL 没有指向恶意链接。

  例子1

&lt;script src=&lt;?= "$script_url&gt;"&gt;
攻击XSS输入
http://evil.org/evil.js
将动态内容替换
将$script_url替换为恶意 XSS 输入:
&lt;script src="http://evil.org/evil.js"&gt;

  例子2

&lt;img src=”&lt;?= $img_url&gt;”&gt;
攻击XSS输入
javascript:evil_script()
将动态内容替换
将$img_url替换为恶意XSS输入:
&lt;img src=” javascript:evil_script()”&gt;

  分析

  一般情况下尽量不要让 URL 的值被用户控制。如果用户需要自己定义自己的风格及显示效果,也不能让用户直接控制整个 URL 的内容,而是提供预定义好的风格供用户设置、装配,然后由后台程序根据用户的选择组合成安全的 URL 输出。

  字符集编码

  浏览器需要知道字符集编码才能正确地显示网页。如果字符集编码没有显式在 content-type 或meta 中定义,浏览器会有算法猜测网页的字符集编码。譬如<script>alert(document.cookie)</script> 的 UTF-7 编码为:

+ADw-script+AD4-alert(document.cookie)+ADw-/script+AD4-

  如果+ADw-script+AD4-alert(document.cookie)+ADw-/script+AD4-作为动态内容位于网页的顶端并传送到浏览器端,IE 会认为此网页是 UTF-7 编码,从而使网页不能正常显示。

  解决方案

  显式定义网页的字符集编码,譬如

&lt;meta http-equiv=content-type content="text/html; charset=UTF-8"&gt;

  动态内容为JavaScript事件处理函数的参数

  JavaScript 事件处理函数如 onClick/onLoad/onError/onMouseOver/ 的参数可能包含动态内容。

  例子

&lt;input type="button" value="go to" onClick='goto_url("&lt;?= $target_url&gt;");'&gt;
攻击XSS输入
foo&amp;quot;);evil_script(&amp;quot;
将动态内容替换
HTML 解析器会先于 JavaScript 解析器解析网页,将$target_url 替换为恶意 XSS 输入:
&lt;input type="button" value="go to" onClick='goto_url("foo");evil_script("");'&gt;
动态内容位于 JavaScript 代码段中

例子 lt;SCRIPT language=javascript1.2gt; var msg=lt;?= $welcome_msg?gt; ; // lt;/SCRIPTgt;攻击XSS输入1Hello; evil_script(); //将动态内容替换将 $welcome_msg 替换为恶意 XSS 输入:lt;

  例子

&lt;SCRIPT language="javascript1.2"&gt; var msg='&lt;?= $welcome_msg?&gt; '; // … &lt;/SCRIPT&gt;
攻击XSS输入1
Hello'; evil_script(); //
将动态内容替换
将 $welcome_msg 替换为恶意 XSS 输入:
&lt;SCRIPT language="javascript1.2"&gt; var msg='Hello'; evil_script(); //'; // … &lt;/SCRIPT&gt;
攻击XSS输入2
Hello&lt;/script&gt;&lt;script&gt;evil_script();&lt;/script&gt;&lt;script&gt;
将动态内容替换
将$welcome_msg 替换为恶意 XSS 输入:
&lt;script&gt; var msg = 'Hello&lt;/script&gt; &lt;script&gt;evil_script();&lt;/script&gt; &lt;script&gt;'
 // ... // do something with msg_text &lt;/script&gt;

  分析

  如上文所示,在 JavaScript 背景中使用动态内容需要非常谨慎。一般情况下,尽量避免或减少在 Javascript 的背景下使用动态内容,如果必须使用动态内容,在开发或代码审计时必须考虑这些动态内容可能的取值,是否会导致 XSS 攻击。

  建立PHP库函数校验输入

  Web 开发人员必须了解,仅仅在客户端使用 JavaScript 函数对非法输入进行检测过滤对于构建安全的 WEB 应用是不够的。如上文所述,攻击者可以轻易地借助工具绕过 JavaScript 校验甚至 SSL 加密输入恶意数据。在输出端对动态内容进行编码也只能起到一种双重保护的作用,更重要的应该在服务器端对输入进行校验。PHP 提供了strpos()、strstr()、preg_match()等函数可用于检测非法字符和字符串;preg_replace() 函数可用于替换非法字符串。OWASP PHP Filters 开源项目提供了一些 PHP 库函数用于过滤非法输入可作为参考。一些常见的检测和过滤包括:

  输入是否仅仅包含合法的字符;

  输入如果为数字,数字是否在指定的范围;

  输入字符串是否超过最大长度限制;

  输入是否符合特殊的格式要求,譬如email 地址、IP 地址;

  不同的输入框在逻辑上存在的耦合和限制的关系;

  除去输入首尾的空格;

  总结

  Web 应用的安全性是一个很重要、覆盖范围很广泛的主题。为了防止常见的 XSS 的攻击,Web 开发人员必须明白不能仅仅只在客户端使用 JavaScript 对输入进行检测、过滤;同时还应建立服务器端的输入校验、输出编码库函数;在服务器端检测、过滤输入;根据动态内容所处的背景将特殊字符进行编码后再传送给浏览器端显示。

例子 lt;SCRIPT language=javascript1.2gt; var msg=lt;?= $welcome_msg?gt; ; // lt;/SCRIPTgt;攻击XSS输入1Hello; evil_script(); //将动态内容替换将 $welcome_msg 替换为恶意 XSS 输入:lt;

  例子

&lt;SCRIPT language="javascript1.2"&gt; var msg='&lt;?= $welcome_msg?&gt; '; // … &lt;/SCRIPT&gt;
攻击XSS输入1
Hello'; evil_script(); //
将动态内容替换
将 $welcome_msg 替换为恶意 XSS 输入:
&lt;SCRIPT language="javascript1.2"&gt; var msg='Hello'; evil_script(); //'; // … &lt;/SCRIPT&gt;
攻击XSS输入2
Hello&lt;/script&gt;&lt;script&gt;evil_script();&lt;/script&gt;&lt;script&gt;
将动态内容替换
将$welcome_msg 替换为恶意 XSS 输入:
&lt;script&gt; var msg = 'Hello&lt;/script&gt; &lt;script&gt;evil_script();&lt;/script&gt; &lt;script&gt;'
 // ... // do something with msg_text &lt;/script&gt;

  分析

  如上文所示,在 JavaScript 背景中使用动态内容需要非常谨慎。一般情况下,尽量避免或减少在 Javascript 的背景下使用动态内容,如果必须使用动态内容,在开发或代码审计时必须考虑这些动态内容可能的取值,是否会导致 XSS 攻击。

  建立PHP库函数校验输入

  Web 开发人员必须了解,仅仅在客户端使用 JavaScript 函数对非法输入进行检测过滤对于构建安全的 WEB 应用是不够的。如上文所述,攻击者可以轻易地借助工具绕过 JavaScript 校验甚至 SSL 加密输入恶意数据。在输出端对动态内容进行编码也只能起到一种双重保护的作用,更重要的应该在服务器端对输入进行校验。PHP 提供了strpos()、strstr()、preg_match()等函数可用于检测非法字符和字符串;preg_replace() 函数可用于替换非法字符串。OWASP PHP Filters 开源项目提供了一些 PHP 库函数用于过滤非法输入可作为参考。一些常见的检测和过滤包括:

  输入是否仅仅包含合法的字符;

  输入如果为数字,数字是否在指定的范围;

  输入字符串是否超过最大长度限制;

  输入是否符合特殊的格式要求,譬如email 地址、IP 地址;

  不同的输入框在逻辑上存在的耦合和限制的关系;

  除去输入首尾的空格;

  总结

  Web 应用的安全性是一个很重要、覆盖范围很广泛的主题。为了防止常见的 XSS 的攻击,Web 开发人员必须明白不能仅仅只在客户端使用 JavaScript 对输入进行检测、过滤;同时还应建立服务器端的输入校验、输出编码库函数;在服务器端检测、过滤输入;根据动态内容所处的背景将特殊字符进行编码后再传送给浏览器端显示。

例子 lt;SCRIPT language=javascript1.2gt; var msg=lt;?= $welcome_msg?gt; ; // lt;/SCRIPTgt;攻击XSS输入1Hello; evil_script(); //将动态内容替换将 $welcome_msg 替换为恶意 XSS 输入:lt;

  例子

&lt;SCRIPT language="javascript1.2"&gt; var msg='&lt;?= $welcome_msg?&gt; '; // … &lt;/SCRIPT&gt;
攻击XSS输入1
Hello'; evil_script(); //
将动态内容替换
将 $welcome_msg 替换为恶意 XSS 输入:
&lt;SCRIPT language="javascript1.2"&gt; var msg='Hello'; evil_script(); //'; // … &lt;/SCRIPT&gt;
攻击XSS输入2
Hello&lt;/script&gt;&lt;script&gt;evil_script();&lt;/script&gt;&lt;script&gt;
将动态内容替换
将$welcome_msg 替换为恶意 XSS 输入:
&lt;script&gt; var msg = 'Hello&lt;/script&gt; &lt;script&gt;evil_script();&lt;/script&gt; &lt;script&gt;'
 // ... // do something with msg_text &lt;/script&gt;

  分析

  如上文所示,在 JavaScript 背景中使用动态内容需要非常谨慎。一般情况下,尽量避免或减少在 Javascript 的背景下使用动态内容,如果必须使用动态内容,在开发或代码审计时必须考虑这些动态内容可能的取值,是否会导致 XSS 攻击。

  建立PHP库函数校验输入

  Web 开发人员必须了解,仅仅在客户端使用 JavaScript 函数对非法输入进行检测过滤对于构建安全的 WEB 应用是不够的。如上文所述,攻击者可以轻易地借助工具绕过 JavaScript 校验甚至 SSL 加密输入恶意数据。在输出端对动态内容进行编码也只能起到一种双重保护的作用,更重要的应该在服务器端对输入进行校验。PHP 提供了strpos()、strstr()、preg_match()等函数可用于检测非法字符和字符串;preg_replace() 函数可用于替换非法字符串。OWASP PHP Filters 开源项目提供了一些 PHP 库函数用于过滤非法输入可作为参考。一些常见的检测和过滤包括:

  输入是否仅仅包含合法的字符;

  输入如果为数字,数字是否在指定的范围;

  输入字符串是否超过最大长度限制;

  输入是否符合特殊的格式要求,譬如email 地址、IP 地址;

  不同的输入框在逻辑上存在的耦合和限制的关系;

  除去输入首尾的空格;

  总结

  Web 应用的安全性是一个很重要、覆盖范围很广泛的主题。为了防止常见的 XSS 的攻击,Web 开发人员必须明白不能仅仅只在客户端使用 JavaScript 对输入进行检测、过滤;同时还应建立服务器端的输入校验、输出编码库函数;在服务器端检测、过滤输入;根据动态内容所处的背景将特殊字符进行编码后再传送给浏览器端显示。

原文转自: http://www.uml.org.cn/Test/201407161.asp
### XSS 跨站脚本攻击概述 XSS(Cross-Site Scripting)是一种常见的Web应用程序安全漏洞,允许攻击者将恶意脚本注入到网页中。这些脚本会在受害者的浏览器上执行,从而窃取敏感数据或进行其他有害活动。 #### 基于DOM的XSS 基于DOM的XSS是指攻击者通过操控客户端JavaScript,使得恶意脚本被执行。这种类型的攻击不依赖于服务器端,而是通过修改浏览器中运行的JavaScript来实现[^1]。 #### 反射型XSS 反射型XSS也被称为非持久性跨站点脚本攻击。其特点是攻击者注入的数据会直接反映在HTTP响应中。一个典型的例子是一个带有XSS攻击向量的链接,每次攻击都需要用户的点击才能生效[^2]。 #### 存储型XSS 存储型XSS则是指攻击者提交的内容被永久存入目标系统的数据库或其他文件内,并且当受害者浏览含有该内容的页面时就会触发攻击。这类攻击的影响范围更广,因为一旦成功植入,所有访问受影响资源的人都可能成为潜在的目标[^3]。 --- ### Web 应用程序中的XSS 测试方法 为了有效检测并修复存在的XSS漏洞,在开发周期的不同阶段都应该实施相应的测试策略: #### 自动化工具扫描 利用专门设计用于发现Web应用安全隐患的安全评估软件来进行初步筛查。例如OWASP ZAP、Burp Suite等都提供了强大的功能帮助识别各种形式的XSS缺陷。 #### 手工渗透测试 对于某些复杂场景下的逻辑错误所引发的隐蔽性较高的XSS问题,则需依靠经验丰富的安全专家采用手工方式深入挖掘。这通常涉及到模拟真实世界里的攻击行为模式以及尝试不同的输入组合以期找到突破口。 #### 单元/集成测试案例编写 开发者可以在编码过程中加入针对特定函数接口调用处可能出现的风险点编写的单元测试或者集成测试用例,确保新特性上线前已经充分考虑到了安全性方面的要求。 ```python def test_xss_protection(): # 创建一个包含特殊字符字符串作为测试输入 payload = "<script>alert('XSS')</script>" # 将payload传递给待测的应用程序组件处理... result = app.process_input(payload) # 验证返回的结果不会导致任何HTML标签未转义的情况发生 assert '<' not in result and '>' not in result, "可能存在XSS风险" ``` --- ### 预防与缓解措施建议 采取有效的防御手段可以大大降低遭受XSS攻击的可能性: - **输出编码**:始终对来自不可信源的数据进行适当转换后再显示出来;比如使用`htmlspecialchars()` PHP内置函数把尖括号替换成对应的实体表示法。 - **CSP (Content Security Policy)** :定义严格的加载外部资源白名单机制,阻止非法来源引入任意JS代码片段。 - **HttpOnly Cookies** : 设置Cookie属性为HttpOnly状态,即使存在XSS也能防止JavaScript读取它们。 - **框架自带保护**:现代前端库如React.js默认会对模板插值部分做必要的过滤工作,减少程序员犯错几率的同时提高了整体安全性水平。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值