Low
分析
上来先随便输个 Name 和 Message,可以看到我们的评论被添加在下面了
点到其他分栏再点回来时,仍旧存在
推测数据被放入了数据库中,每次访问网页会查询数据库,将所有的评论都显示出来
尝试在 Name 输入框输入 script 标签,然而句子还没输完就输不进去了,应该是有 maxlength 属性的限制
在 Name 输入框的位置 右键->查看元素,将 maxlength 改为 50
再输入就可以了
提交以后,每次访问这个网页都会弹两次窗…神烦233
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
<?php
if( isset( $_POST[ 'btnSign' ] ) ) { $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] );
$message = stripslashes( $message ); $message = mysql_real_escape_string( $message );
$name = mysql_real_escape_string( $name );
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
}
?>
|
信息插入之时,通过一些安全函数(如 mysql_real_escape_string ),使得 SQL 注入失效
显示的时候,index.php 在 64 行处调用了 dvwaGuestbook 函数,这个函数在 dvwaPage.inc.php 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
function dvwaGuestbook() { $query = "SELECT name, comment FROM guestbook"; $result = mysql_query( $query );
$guestbook = '';
while( $row = mysql_fetch_row( $result ) ) { if( dvwaSecurityLevelGet() == 'impossible' ) { $name = htmlspecialchars( $row[0] ); $comment = htmlspecialchars( $row[1] ); } else { $name = $row[0]; $comment = $row[1]; }
$guestbook .= "<div id=\"guestbook_comments\">Name: {$name}<br />" . "Message: {$comment}<br /></div>\n"; } return $guestbook; }
|
显示时只有当难度为 impossible,才会用 htmlspecialchars 转化为 html 实体,所以存在 XSS 漏洞,而且因为信息存储在服务器端,其他用户访问网页时,也会受到恶意脚本攻击,所以称其为存储型 XSS
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
|
<?php
if( isset( $_POST[ 'btnSign' ] ) ) { $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] );
$message = strip_tags( addslashes( $message ) ); $message = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message );
$name = str_replace( '<script>', '', $name ); $name = mysql_real_escape_string( $name );
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
}
?>
|
与我上一篇文章中写到的 反射型 XSS medium 难度相似,对 name 输入框中的 <script> 做了替换,可以通过大小写,双写,加 src 属性,使用其他标签来绕过
而对 message 的内容则是调用了 htmlspecialchars 函数来将一些字符(如 < > 等)转换为 html 实体,也就是说这个输入框不能再被 XSS 漏洞利用了,但 name 输入框的内容仍能被视作 html 代码来解释
我们可以考虑在前端将 maxlength 的值改大,也可以考虑抓包直接修改 name 的值
High
源码
1 2 3 4
|
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); $name = mysql_real_escape_string( $name );
|
加了正则,还是可以继续在 name 输入框用其他标签绕过
Impossible
源码
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 32 33 34 35
| <?php
if( isset( $_POST[ 'btnSign' ] ) ) { checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] );
$message = stripslashes( $message ); $message = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message );
$name = stripslashes( $name ); $name = mysql_real_escape_string( $name ); $name = htmlspecialchars( $name );
$data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' ); $data->bindParam( ':message', $message, PDO::PARAM_STR ); $data->bindParam( ':name', $name, PDO::PARAM_STR ); $data->execute(); }
generateSessionToken();
?>
$name = htmlspecialchars( $row[0] ); $comment = htmlspecialchars( $row[1] );
|
查询数据库时使用 PDO 技术,显示评论时对两个字段都使用 htmlspecialchars 防 SQL 注入与 XSS,效果显著