声明:
由于笔者能力有限,难免出现各种错误和漏洞。全文仅作为个人笔记,仅供参考。
笔记内容来源于各类网课、书籍。
本章节内容来源:《Web安全攻防渗透测试实战指南》
三、XSS
1. XSS基础
1.1 XSS漏洞介绍
跨站脚本(Cross-Site Scripting,检测为XSS或跨站脚本或跨站脚本攻击),是一种针对网页应用程序的安全漏洞攻击技术,是代码注入的一种。
它允许恶意用户将脚本代码注入网页中,其他用户在浏览网页会受到影响。恶意用户利用XSS攻击成功后,可能会进行高权限的操作、获取私密网页内容、会话劫持等操作。
XSS分为反射型、存储型、DOM型。
1.2 XSS漏洞原理
1.2.1 反射型
又称为非持久性XSS,这种攻击是一次性的。
攻击方式:攻击者通过电子邮件等方式,将包含XSS代码的恶意链接发送给目标用户。当目标用户访问该链接时,服务器接收目标用户的请求并进行处理,然后服务器把带有XSS代码的数据发送给用户浏览器,浏览器解析XSS代码的恶意脚本,就会触发XSS漏洞。
举一个反射型XSS利用的例子:
攻击者找到一个可以利用反射型XSS的网址,发送给用户 。XSS脚本使网页重定位到攻击者的恶意URL地址,恶意URL地址内加载了Beef的hook.js,当用户点击了攻击者发送的网址,就会被Beef控制,攻击者可以进行一些操作。
1.2.2 存储型
又称为持久型XSS,攻击脚本被存储在目标服务器的数据库或文件中,具有很高的隐蔽性。
攻击方式:这种攻击多见于论坛、博客和留言板,攻击者在发帖的过程中,将恶意脚本混在正常信息中一起注入帖子中。随着帖子被服务器存储下来,恶意脚本也被存储在服务器中。当其他用户浏览了这个被恶意注入脚本的帖子时,就会触发其中的恶意代码。
与反射型不同的是,反射型XSS在URL中可以提现出部分恶意代码,如果仔细对待不明链接,可以大大减少收到的工具。但是存储型XSS是在URL返回的内容中,无法通过URL分辨有无恶意代码,危害更大。
1.2.3 DOM型XSS
DOM全称Document Object Model,使用DOM可以使程序和脚本能够动态访问和更新文档的内容、结构或样式。
DOM型XSS其实一种特殊的反射性XSS,它是基于DOM文档对象模型的一种漏洞。
由于DOM是在客户端修改节点的,所以基于DOM型的XSS漏洞不需要与服务器进行交互,它只发生在客户端处理数据阶段。
攻击方式:用户请求一个进过专门设计的URL,它由攻击者提交,而且其中包含XSS代码。服务器的响应不会以任何形式包含攻击者脚本。当用户的浏览器处理这个响应,DOM对象会处理XSS代码,导致XSS漏洞。
1.3 反射型XSS攻击
环境:DVWA的XSS(Reflected)[Low]
(1) 正常提交
提交后,会将提交的数据放在URL的参数位置,这就构成了一个带参数GET请求。
同时我们的数据显示在了html中的<pre>标签中。
(2) 触发XSS
我们尝试闭合<pre>标签,让恶意脚本插入其中并得到执行。
</pre><script>alert(document.cookie)</script>
脚本触发:
注入的脚本:
(3) 代码分析
Low级别的ReflectedXSS的后端代码。
<?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>';
}
?>
后端处理如下:
通过if判断参数列表中有无name键的存在,并且获取到的name键的值不为空,进行下一步。
if内没有进行任何字符检测过滤,直接将我们提交的参数进行字符串拼接,并回显。
漏洞触发原因:
由于没有对用户输入的参数进行任何检测,导致用户可以进行恶意代码的注入。
其他:
在medium等级下,对某些标签有过滤,但是依然可使用其他标签触发(例如:img标签)。
1.4 存储型XSS攻击
环境:DVWA的XSS(Stored)[Low]
(1) 正常提交
数据提交方式是由POST提交。数据回显在HTML中。
(2) 存储恶意脚本并触发XSS
存储并触发XSS:
<script>alert(document.cookie);</script>
存储的恶意脚本:
恶意脚本已经存储到数据库中。
以后任何用户访问该URL连接,都会触发XSS,危害很大。
(3) 代码分析
Low级别的StoredXSS的后端代码。
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitize name input
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
//mysql_close();
}
?>
这里依然是没有对参数进行任何过滤和检测,导致的存储型XSS的出现。
1.5 DOM型XSS攻击
(1) 正常提交
我们可以看到数据由页面中js处理,服务器对输入的参数不进行处理。这里有可能存在DOM型XSS。数据在option标签中回显。
(2) 触发XSS
<script>alert(document.cookie);</script>
注入的恶意脚本:
(3) 代码分析
前端代码:
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}
document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
这里是DOM型的XSS,后端没有对参数做任何处理。
DOM型和反射性的区别是:
DOM型的恶意代码不经过服务器处理,反射型的进过服务器处理。其实DOM型算是特殊的反射型。
2. XSS进阶
2.1 XSS常用语句
- <script>alert(1);</script>
- <img src=x οnerrοr=alert(1) >
- <img src=javascript:alert(1)>
- <svg οnlοad=alert(1)>
- <a href=javascript:alert(1)>
- <a href=javascript:alert(1)>hack</a>
- <scr<script>ipt>alert(1);</scr</script>ipt> // 双写
- '><script>alert(0)</script> // 闭合前面属性和标签
- <? echo('<script>alert("XSS")</script>'); ?> // php输出恶意脚本
2.2 编码绕过
常见的JS编码,HTML实体编码,URL编码绕过。
2.2.1 JS编码
- 三个八进制数字,如果个数不够,在前面补0。例如'e'的编码:'\145'
- 两个十六进制数字,如果个数不够,在前面补0。例如'e'的编码:'\x65'
- 四个十六进制数字(Unicode编码),如果个数不够,在前面补0。例如'e'的编码:'\u0065'
- 对于一些特殊字符,使用C类型的转义风格。例如\r,\n,\\
2.2.2 HTML实体编码
- 命名实体:以&开头,以分号结尾的,例如'<'的编码是:"<"
- 字符编码:十进制、十六进制ASCII码或Unicode字符编码,样式为"&#数值",例如'<'的编码为"<",和"<"
2.2.3 URL编码
例如alert的URL编码为:
- %61%6c%65%72%74 (一次全编码)
- %25%36%31%25%36%63%25%36%35%25%37%32%25%37%34 (二次全编码)
在使用XSS编码测试时,需要考虑HTML渲染顺序,特别是针对多种编码组合时,需要选择合适的编码方式进行测试。
3. XSS漏洞修复建议
- 过滤数据,包括单引号,双引号,大小于号,on*等非法字符。
- 对字符串进行强制编码,将特殊的字符进行编码(HTML实体编码)