环境:
phpstudy 2018 PHP-5.5.38 apache 2.4.23
漏洞:
SQL注入
stripslashes+addslashes引起的注入
注册界面/ucenter/reg.php存在sql注入漏洞,此页面为会员注册界面,下面是部分代码:
<?php include('../system/inc.php'); if(isset($_SESSION['user_name'])){ header('location:index.php'); }; if(isset($_POST['submit'])){ $username = stripslashes(trim($_POST['name'])); // 检测用户名是否存在 $query = mysql_query("select u_id from xtcms_user where u_name='$username'"); if(mysql_fetch_array($query)){ echo '<script>alert("用户名已存在,请换个其他的用户名");window.history.go(-1);</script>'; exit; } $result = mysql_query('select * from xtcms_user where u_email = "'.$_POST['email'].'"'); if(mysql_fetch_array($result)){ echo '<script>alert("邮箱已存在,请换个其他的邮箱");window.history.go(-1);</script>'; exit; }
可以看到”$username”来自POST请求包中,其中先经过”trim“和”stripslashesh”函数处理。函数方法如下:
- trim()函数
移除字符串两侧的空白字符或其他预定义字符(默认为NULL、\t、\n、\r、空格等)。
- stripslashesh
反引用一个引用字符串。如果 magic_quotes_sybase 项开启,反斜线将被去除,但是两个反斜线将会被替换成一个。
由此可见,$username变量经过stripslashes()和trim()函数处理后,直接拼接进查询语句中,由单引号闭合。但既然存在去除反斜杠,前面应该由addlashes()函数添加反斜杠:因此进一步追踪包含文件,../system/inc.php

逐一查看,最后在../system/library.php文件中看到:
<?php if (!defined('PCFINAL')) { exit('Request Error!'); } if (!get_magic_quotes_gpc()) { if (!empty($_GET)) { $_GET = addslashes_deep($_GET); } if (!empty($_POST)) { $_POST = addslashes_deep($_POST); } $_COOKIE = addslashes_deep($_COOKIE); $_REQUEST = addslashes_deep($_REQUEST); } function addslashes_deep($_var_0) { if (empty($_var_0)) { return $_var_0; } else { return is_array($_var_0) ? array_map('addslashes_deep', $_var_0) : addslashes($_var_0); } }
分析这个文件,里面自定义了addslashes_deep函数,本意是为了防止注入,对get、post传入的参数用”adddslashes()”进行了转义处理,就是对单引号(’)、双引号(”)、反斜线(\)与 NUL(null 字符)前加入反斜线。乍一看单独存在是没有问题的,但是结合之前”stripslashesh()“函数,增加在减少岂不是相当于没有。那么漏洞点就来了。
回到/ucenter/reg.php,执行查询语句后的结果给到了”$query“变量,但是这里是没有返回$query的值的,故这里的利用方式为使用时间盲注。直接sqlmap跑一波。

那么同样的思路,所有引用了”stripslashes()函数”和引用”system/inc.php”或”/system/library.php”的地方都有一样的漏洞呢?
全局搜索stripslashes,得到如下

- active.php

- repass.php

- /wap/login.php
<?php include('../system/inc.php'); $op=$_GET['op']; if(isset($_POST['submit'])){ null_back($_POST['u_name'],'请输入用户名'); null_back($_POST['u_password'],'请输入密码'); $u_name = $_POST['u_name']; $u_password = $_POST['u_password']; $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1'; $result = mysql_query($sql); if(!! $row = mysql_fetch_array($result)){ $_data['u_loginnum'] = $row['u_loginnum']+1; $_data['u_loginip'] =$_SERVER["REMOTE_ADDR"]; $_data['u_logintime'] =date('y-m-d h:i:s',time()); if(!empty($row['u_end'])) $u_end= $row['u_end']; if(time()>$u_end){ $_data['u_flag'] =="0"; $_data['u_start'] ==""; $_data['u_end'] ==""; $_data['u_group'] =1; }else{ $_data['u_flag'] ==$row["u_flag"]; $_data['u_start'] ==$row["u_start"]; $_data['u_end'] ==$row["u_end"]; $_data['u_group'] =$row["u_group"]; } mysql_query('update xtcms_user set '.arrtoupdate($_data).' where u_id ="'.$row['u_id'].'"'); $_SESSION['user_name']=$row['u_name']; $_SESSION['user_group']=$row['u_group']; if($_POST['brand1']){ setcookie('user_name',$row['u_name'],time()+3600 * 24 * 365); setcookie('user_password',$row['u_password'],time()+3600 * 24 * 365); } header('location:user.php'); }else{ alert_href('用户名或密码错误或者尚未激活','login.php?op=login'); } } if(isset($_POST['reg'])){ $username = stripslashes(trim($_POST['name'])); // 检测用户名是否存在 $query = mysql_query("select u_id from xtcms_user where u_name='$username'"); if(mysql_fetch_array($query)){ echo '<script>alert("用户名已存在,请换个其他的用户名");window.history.go(-1);</script>'; exit; }
这几个文件中,不但有stripslashes函数,还引用了/system/inc.php文件,故存在同样的注入问题。
template/wapian/vlist.php注入
继续根据seay自动审计工具,发现vlist.php存在注入漏洞,关键代码如下:

对“$_GET[‘cid’]变量进行一个判断,不为0的时候,直接拼接到查询语句中,这里无任何防护,但进一步审查代码,也未发现输出点,sqlmap直接跑。
admin/cms_backup.php注入
关键代码如下:

在代码中可以看到,$vals变量经过array_map()函数处理后,全部经过了addlashes()转义处理来防止注入,之后经过$vals=”‘”.$vals.”‘”;语句处理,添加单引号包裹,就完全杜绝了sql注入的可能性,无法构造闭合。