/include/common.inc.php
第30-36行
对$_GET、$_POST、$_COOKIES、$_REQUEST
使用deep_addslashes()
函数过滤一遍,漏了$_SERVER
if(!get_magic_quotes_gpc()) { $_POST = deep_addslashes($_POST); $_GET = deep_addslashes($_GET); $_COOKIES = deep_addslashes($_COOKIES); $_REQUEST = deep_addslashes($_REQUEST); }
追踪一下deep_addslashes()
函数
/include/common.fun.php
第14-28行
function deep_addslashes($str) { if(is_array($str)) { foreach($str as $key=>$val) { $str[$key] = deep_addslashes($val); } } else { $str = addslashes($str); } return $str; }
12:$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : ''; 19:$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
$ad_id
没有使用单引号双引号包括所以addslashes()
函数不起作用
getone()
方法位于/include/mysql.class.php
第61
行,作用是执行SQL
语句并输出
function getone($sql, $type=MYSQL_ASSOC){ $query = $this->query($sql,$this->linkid); $row = mysql_fetch_array($query, $type); return $row; }
$ad_id
只是用trim()
函数去除首尾的空格,故存在SQL
注入漏洞
因为没有对$_SERVER
进行过滤,所以使用X-Forwarded-For
或者CLIENT-IP
可以伪装ip
进行SQL
注入
全局搜索ip
找到guset_book.php
里面有关于ip
的SQL
语句
第77-79行
$sql = "INSERT INTO " . table('guest_book') . " (id, rid, user_id, add_time, ip, content) VALUES ('', '$rid', '$user_id', '$timestamp', '$online_ip', '$content')"; $db->query($sql);
$online_ip
就是getip()
追踪到common.fun.php
中getip()
函数
第106-133行
function getip()
{
if (getenv('HTTP_CLIENT_IP'))
{
$ip = getenv('HTTP_CLIENT_IP');
}
elseif (getenv('HTTP_X_FORWARDED_FOR'))
{
$ip = getenv('HTTP_X_FORWARDED_FOR');
}
elseif (getenv('HTTP_X_FORWARDED'))
{
$ip = getenv('HTTP_X_FORWARDED');
}
elseif (getenv('HTTP_FORWARDED_FOR'))
{
$ip = getenv('HTTP_FORWARDED_FOR');
}
elseif (getenv('HTTP_FORWARDED'))
{
$ip = getenv('HTTP_FORWARDED');
}
else
{
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
所以可以使用X-Forwarded-For
或者CLIENT-IP
进行SQL
注入
评论区出现SQL
注入结果
全局搜索getip
发现comment.php
里面有一处SQL
语句
第133-135行
$sql = "INSERT INTO ".table('comment')." (com_id, post_id, user_id, type, mood, content, pub_date, ip, is_check) VALUES ('', '$id', '$user_id', '$type', '$mood', '$content', '$timestamp', '".getip()."', '$is_check')"; $db->query($sql);
其它参数都有addslashes()
函数过滤而getip()
的值没有,所以存在SQL
注入漏洞,和上面一样是insert
型注入,就不演示了
第22-23行
$admin_name = isset($_POST['admin_name']) ? trim($_POST['admin_name']) : ''; $admin_pwd = isset($_POST['admin_pwd']) ? trim($_POST['admin_pwd']) : '';
然后第31行判断
if(check_admin($admin_name, $admin_pwd))
追踪check_admin()
函数到common.fun.php
176-188行
function check_admin($name, $pwd) { global $db; $row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$name' and pwd = md5('$pwd')"); if($row['num'] > 0) { return true; } else { return false; } }
因为编码是gbk2312
,$name
使用了addslashes()
函数过滤,所以存在SQL
注入漏洞,可造成万能密码进后台
第77行
$row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$user_name'");
$user_name
使用了addslashes()
函数过滤但是网页编码是gbk2312
,所以存在宽字节注入
138行
$email = !empty($_POST['email']) ? trim($_POST['email']) : '';
160行
$sql = "INSERT INTO ".table('user')." (user_id, user_name, pwd, email, reg_time, last_login_time) VALUES ('', '$user_name', md5('$pwd'), '$email', '$timestamp', '$timestamp')";
$email
使用单引号包围,有addslashes()
函数过滤,网页编码是gbk2312
所以存在宽字节注入
第135行
$user_name = !empty($_POST['user_name']) ? trim($_POST['user_name']) : '';
第154-156行
if($db->getone("SELECT * FROM ".table('user')." WHERE user_name='$user_name'")){ showmsg('该用户名已存在'); }
故存在宽字节注入,但是$user_name
有大于4小于16的长度限制,不好利用,有点鸡肋
63-70行
elseif($act=='edit') { $sql = "select * from ".table('navigate')." where navid = ".$_GET['navid']; $nav = $db->getone($sql); $smarty->assign('nav',$nav); $smarty->assign('act', $act ); $smarty->display('nav_info.htm'); }
$_GET['navid']
直接接在后面,存在SQL注入漏洞
第78-85行
elseif($_REQUEST['act'] == 'del') { $sql = "DELETE FROM ".table('attachment')." WHERE att_id = ".$_GET['att_id']; if(!$db->query($sql)){ showmsg('删除附加属性出错', true); } showmsg('删除附加属性成功','attachment.php', true); }
$att_id
直接接在后面,存在SQL注入漏洞
第101行
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : '';
第106行
$ad = $db->getone("SELECT ad_id, ad_name, time_set, start_time, end_time, content, exp_content FROM ".table('ad')." WHERE ad_id=".$ad_id);
$ad_id
直接接在后面,存在SQL注入漏洞
后台注入大多都是直接拼接或者宽字节造成的,挺多的所以这里略了
注册了一个用户在个人信息里面出现了一些注册信息,查看源代码看是否存在存储型XSS
135-139行
$user_name = !empty($_POST['user_name']) ? trim($_POST['user_name']) : ''; $pwd = !empty($_POST['pwd']) ? trim($_POST['pwd']) : ''; $pwd1 = !empty($_POST['pwd1']) ? trim($_POST['pwd1']) : ''; $email = !empty($_POST['email']) ? trim($_POST['email']) : ''; $safecode = !empty($_POST['safecode']) ? trim($_POST['safecode']) : '';
对邮箱$email
只有个trim()
以及addslashes()
,所以存在存储型XSS,直接在网页表单写入payload会被前端检测无法提交,所以抓包改
第266行
$content = !empty($_POST['content']) ? filter_data($_POST['content']) : '';
评论的内容采用filter_data()
函数过滤
追踪filter_data()
函数,位于common.fun.php
第985-988行
function filter_data($str) { $str = preg_replace("/<(\/?)(script|i?frame|meta|link)(\s*)[^<]*>/", "", $str); return $str; }
很明显漏了img
标签,所以使用img
标签即可,payload:<p><img src=1 onerror=alert(1)></p>
这里必须抓包改,不然会有一个 
干扰XSS payload
导致无法执行
第742-751行
elseif ($act == 'pay'){ include 'data/pay.cache.php'; $price = $_POST['price']; $id = $_POST['id']; $name = $_POST['name']; if (empty($_POST['pay'])) { showmsg('对不起,您没有选择支付方式'); } include 'include/payment/'.$_POST['pay']."/index.php"; }
$_POST['pay']
前后加了文件,可以使用../
进行目录遍历,后面的/index.php
如果php
版本低于5.3.4
且magic_quotes_gpc=off
则可以使用%00
截断,导致任意文件包含。还可以使用.号路径长度截断,Windows
下目录最大长度为256
字节,Linux
下目录最大长度为4096
字节
可配合用户头像上传上传图片马使用
第779-785行
if (!empty($_POST['face_pic1'])){ if (strpos($_POST['face_pic1'], 'http://') != false && strpos($_POST['face_pic1'], 'https://') != false){ showmsg('只支持本站相对路径地址'); } else{ $face_pic = trim($_POST['face_pic1']); }
它本来的意思是想不能包含http://
或者https://
应该用!==
,但是他用了!=
,根据php弱类型strpos()
返回值为0是和false相等的,故能够绕过造成SSRF漏洞
第787-789行
if(file_exists(BLUE_ROOT.$_POST['face_pic3'])){ @unlink(BLUE_ROOT.$_POST['face_pic3']); }
face_pic1
和face_pic2
为空时,输入的任意存在文件能被删除
我新建了一个test.php文件在网站根目录下
burpsuite
抓包传入路径
test.php
已被删除
第615-617行
if (file_exists(BLUE_ROOT.$_POST['lit_pic'])) { @unlink(BLUE_ROOT.$_POST['lit_pic']); }
很明显的任意文件删除
刚入坑审计,这是审计的第二个cms,目前使用的就是rips
以及Seay
扫一下可能存在漏洞的地方,有的漏洞是扫不出来的需要自己去发现,找SQL注入可以全局搜索一下SELECT、UPDATE、INSERT、DELETE
等关键字,还可以使用查找危险函数的方法找漏洞比如unlink()
函数可能存在任意文件删除。有的时候看代码太过繁琐抽象可以尝试功能点审计,比如找到一处上传或者留言板等,去看对应的代码,对变量进行回溯,看是否可控。像我这样刚入坑审计的菜鸟无疑是很枯燥和困难的,代码复杂难懂量大,但是方法不难,所以更多的还是耐心、仔细和坚持。文章中有不足和错误的地方还望师傅们指正。