如果你是一位渗透测试新手,那么我建议你学习本系列文章,通过本系列文章你可以认识常见漏洞以及学会基础php代码审计,在这之前你需要搭建环境DVWA靶场。
一、靶场搭建
首先需要php集成环境,在这里笔者推荐使用phpstudy,下载地址:http://www.phpstudy.net/phpstudy/phpStudy20161103.zip
安装成功后启动如下图所示,Apache和mysql均为绿色接下来下载dvwa,下载地址:https://github.com/ethicalhack3r/DVWA
将其解压放在phpstudy的www文件夹下,点击config文件,将config.inc.php文件里的db_user以及db_psd值均修改为root并保存,复制一份config.inc.php.dist文件并将其与原文件放在同一目录下,修改后缀名为.php,否则在启动时会报错,如下图文件1和3所示接下来登录网站,127.0.0.1/dvwa/index.php,用户名为admin,密码为password。登陆成功后如下图所示:DVWA有三种模式,低中高可以在security中设置,点击右下角view source便可以查看源代码。
二、反射型xss
首先我们从low开始看起,查看源代码
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
代码直接引用了name参数,并且未做任何过滤,此时我们提交恶意代码便会被执行,例如<script>alert(23333)</script>
接下来我们看Medium,代码如下
<?php
header ("X-XSS-Protection: 0");
// 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>";
}
?>
可以看到使用了 str_replace
函数,来看下这个函数的语法规则:str_replace(find,replace,string,count)
,其中find,replace,string是必须有的,count可选,表达的意思是将find的值替换为replace,count是对替换数进行计数,在这里我们需要注意的是str_replace函数不区分大小写并且仅进行一次替换。来看medium的源代码,采用黑名单思想,将<script>
标签替换为空,我们可以很轻易的进行绕过,比如<scr<script>ipt>alert(2333) <scr</script>ipt>
或者其他不包含<script>
标签的恶意代码例如<svg/onload=alert('XSS')>
最后来看high级别的,源代码如下
<?php
header ("X-XSS-Protection: 0");
// 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>";
} /
?>
可以看到在这里使用了preg_replace
这一函数,来看看语法规则mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换,本实例中使用空格替换script任何一个字母,这样使得大小写字母,类似于middle中的双写绕过均无效,但我们可以使用body标签等进行绕过,例如<BODY ONLOAD=alert('XSS')>
最后来看下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();
?>
可以看到里边有这样一段代码$name = htmlspecialchars( $_GET[ 'name' ] );
对预定义字符进行了实体编码,从而防止了xss的发生,这也是我们在做防御的过程中常用到的一种方法。