概念
XSS攻击,是指攻击者在Web页面中输入恶意的JavaScript脚本,而Web应用程序没有对用户的输入进行过滤或处理就直接执行,将结果输出在网页中。如果恶意JavaScript脚本被存储到后端服务器中,用户打开该Web页面时,恶意脚本则可能在浏览器中自动执行。XSS攻击依赖于JavaScript脚本的执行。一般,攻击者插入恶意脚本后,需要将脚本执行结果显示出来,因此,XSS攻击常见于网站中有用户输入且能够显示的地方,如文章发表、评论回复、留言板等。
目的
以一种或另一种方式,窃取登录用户的cookie。
反射型XSS
反射型XSS,是指攻击者在页面中插入恶意JavaScript脚本,当合法用户正常请求页面时,该恶意脚本会随着Web页面请求一并提交给服务器,服务器处理后进行响应,响应由浏览器解析后将JavaScript脚本的执行结果显示在页面中。整个过程就像是一次“客户端—服务器—客户端”的反射过程,恶意脚本没有经过服务器的过滤或处理,就被反射回客户端直接执行并显示相应的结果。反射型XSS需要攻击者将带有恶意脚本的链接发送给其他用户,并诱惑用户点击该链接后才会发生。反射型XSS只有在用户点击时才会触发,且只执行一次,恶意代码不会在服务器中存储,因此也被称为“非持久型XSS”。
XSS漏洞分析
利用XSS漏洞时,首先寻找输入点。输入点一般是页面与用户交互之处,用户在输入点输入的数据会被提交到服务器,如URL、表单等。
其次,寻找输出点,确定Web应用程序是否将用户输入的数据显示在网页中。有的业务场景是用户输入数据后,在页面中立刻就能找到输出点,如留言板、评论等。但是,也有不在前端页面中显示的,如私信、意见反馈等,需要人工处理的,则会给XSS攻击增加难度。
最后,进行恶意代码测试。一旦知道了输入点、输出点,就可以构造含有恶意JavaScript脚本的输入,测试页面的输出。
XSS漏洞经常被用来窃取用户的Cookie,用于实施进一步的攻击,如篡改数据、盗取用户、修改用户设置等;也被用于网络钓鱼,使用短信、邮件群发恶意链接,诱导用户点击以获取用户输入敏感信息;甚至可以结合其他漏洞,对服务器发起攻击、植入木马等。在满足具体的业务场景需求时,对XSS攻击的防护较为困难,XSS漏洞范围广、引起的社会影响大,现已受到越来越多的关注。
低水平
查找输入输出点,输入内容会直接显示在页面和URL中
构造恶意脚本
Spoiler: ?name=<script>alert("XSS");</script>.
在输入框输入<script>alert("XSS");</script> 点击submit,显示了alert
弹窗显示cookie <script>alert(document.cookie)</script>,发现已获取cookie。
在将请求的输入包含在输出文本中之前,低级别没有对输入进行检查。
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
中级
中级反射型XSS渗透测试环境增加了一个“Get input”部分实现对输入参数的过滤
“$name=str_replace(′<script>′,′′,$_GET[′name′]);”语句将name参数值中的所有“<script>”字符串替换为空字符串,过滤该JavaScript标签。
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello {$name}</pre>";
}
?>
使用 `str_replace()` 函数来清除 `<script>` 标记是不足以解决XSS漏洞的。应该使用适当的净化方法和输出编码方法,如 `htmlspecialchars()` 函数或使用模板引擎来生成JavaScript。
因此,建议对用户的输入数据进行彻底的验证和净化,包括过滤特殊字符、将HTML标签转义为它们的HTML实体等。此外,推荐使用先进的Web应用程序防火墙(WAF)和安全性别扫描程序来保护您的Web应用程序免受此类攻击。
由中级的脚本可见,该程序只把<script>替换成了空字符串。
输入低水平攻击,显示了alert("XSS")
但是可以使用大小写绕过,大小写绕过,就是将“<script>”字符串中的部分字符改成大写,使改写后的字符串不与原字符串完全一致,如“<sCrIpT>”,从而绕过防护。在DVWA平台的中级反射型XSS渗透测试页面的文本框中输入“<sCrIpT>alert(document.cookie)</script>”
双写绕过,就是利用“<script>”替换成空字符串的机制,使用“<script>”将“<script>”字符串分隔,如“<scr<script>ipt>”,该字符串中的“<script>”字符串被替换成空字符串后,剩余的字符又组成了“<script>”字符串,从而绕过防护。
在DVWA平台的中级反射型XSS渗透测试页面的文本框中输入“<scr<script>ipt>alert(document.cookie)</script>”,将页面Cookie显示在弹窗中
高水平
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello {$name}</pre>";
}
?>
高级反射型XSS渗透测试源代码不再是简单地将“<script>”字符串进行替换,而是使用“$name=preg_replace(′/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i′,′′,$_GET[′name′]);”语句中的preg_replace()函数,基于正则表达式进行替换,且添加“i”修饰符,不区分大小写,以防止发生大小写绕过和双写绕过的XSS攻击。
输入低水平脚本,只显示了一个Hello >
过滤了script标签,可以标签绕过,就是将使用<script>以外的其他HTML标签插入JavaScript脚本,从而绕过防护。
“<img src=#οnerrοr=alert(document.cookie)>”,使用<img>标签绕过,成功将页面Cookie显示在弹窗中
用其他标签绕过,比如常用的<body>标签,输入“<body οnlοad=alert(document.cookie)>”
不可能的水平
使用内置的PHP函数(如“htmlspecialchars()”), 可以转义任何会改变输入行为的值。
// Get input
$name = htmlspecialchars( $_GET[ 'name' ] );
htmlspecialchars()
是一个PHP函数,它的主要作用是将特殊字符转换为HTML实体。这样做的目的是为了防止这些特殊字符被浏览器误解释为HTML代码的一部分,从而避免了潜在的安全问题。
例如,如果你的用户输入包含 <
、>
、"
、'
和 &
等字符,并且你需要在网页上显示这些输入,但不希望浏览器将这些字符解释为HTML标记或实体,那么你可以使用 htmlspecialchars()
函数来转义这些字符。
$input = "<html>Hello, world!</html>";
$output = htmlspecialchars($input);
echo $output;
输出将是:<html>Hello, world!</html>
。
这样,浏览器会正确地显示文本,而不是尝试将其解释为HTML代码。这样可以防止潜在的跨站脚本攻击(XSS)。
请注意,尽管 htmlspecialchars()
有助于防止XSS攻击,但它并不提供完全的保护。为了实现更高级的安全性,应该使用其他方法,如内容安全策略(CSP)或输出编码函数(例如 htmlspecialchars()
)与输入验证和清理的组合。