本文转载自先知社区:https://xz.aliyun.com/t/2668
本文由红日安全成员: 七月火 编写,如有不当,还望斧正。
大家好,我们是红日安全-代码审计小组。最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫 PHP-Audit-Labs 。现在大家所看到的系列文章,属于项目 第一阶段 的内容,本阶段的内容题目均来自 PHP SECURITY CALENDAR 2017 。对于每一道题目,我们均给出对应的分析,并结合实际CMS进行解说。在文章的最后,我们还会留一道CTF题目,供大家练习,希望大家喜欢。下面是 第10篇 代码审计文章:
Day 10 - Anticipation
题目叫做预期,代码如下:
漏洞解析 :
这道题目实际上讲的是当检测到攻击时,虽然有相应的防御操作,但是程序未立即停止退出,导致程序继续执行的问题。程序在 第一行处 使用 extract 函数,将 POST 请求的数据全都注册成变量, extract 函数的定义如下:
extract :(PHP 4, PHP 5, PHP 7)
功能 :从数组中将变量导入到当前的符号表
定义 : int extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] )
该函数实际上就是把数组中的键值对注册成变量,具体可以看如下案例:
这样我们就可以控制 第7行 处的 pi 变量。程序对 pi 变量进行简单的验证,如果不是数字或者没有设置 pi 变量,程序就会执行 goAway 方法,即记录错误信息并直接重定向到 /error/ 页面。看来程序员这里是对非法的操作进行了一定的处理。但是关键在于,程序在处理完之后,没有立即退出,这样程序又会按照流程执行下去,也就到了 第11行 的 assert 语句。由于前面 pi 变量可以被用户控制,所以在这一行存在远程代码执行漏洞。
例如我们的payload为:pi=phpinfo() (这里为POST传递数据),然后程序就会执行这个 phpinfo 函数。当然,你在浏览器端可能看不到 phpinfo 的页面,而是像下面这样的图片:
但是用 BurpSuite ,大家就可以清晰的看到程序执行了 phpinfo 函数:
为了方便大家理解,笔者这里录制了debug程序的过程:
实际上,这种案例在真实环境下还不少。例如有些CMS通过检查是否存在install.lock文件,从而判断程序是否安装过。如果安装过,就直接将用户重定向到网站首页,却忘记直接退出程序,导致网站重装漏洞的发生。下面我们来看两个真实的案例。
本次实例分析,我们选取的是 FengCms 1.32 。对于一个已经安装好的 FengCms ,当用户再次访问 install/index.php 时,就会导致网站重装。我们来具体看下程序的逻辑:
我们可以看到,如果是第一次安装网站,程序会在 upload 目录下生成一个 INSTALL 文件,用于表示该网站已经安装过(对应上图 25-28行 代码)。当我们再次访问该文件时,程序会先判断 upload 目录下是否有 INSTALL 文件。如果存在,则弹窗提示你先删除 INSTALL 文件才能进行网站重装(对应上图 1-4行 代码)。但是这里注意了,网站在弹出告警信息后,并没有退出,而是继续执行,所以我们在不删除 INSTALL 文件的情况下,仍可以重装网站。
比较有趣的是,原本网站网站成功后,程序会自动删除 upload 目录下的所有文件,来防止攻击者重装网站,然而这段代码却在注释当中,具体原因不得而知。
我们再来看 Simple-Log1.6 网站重装的例子。其 install\index.php 文件中,对网站安装成功的处理有问题,其代码是在下图 17-20行 ,程序只是用 header 函数将其重定向到网站首页,然而程序还是会继续执行下去。
而且程序的安装逻辑其实是有问题的,安装步骤由 $setup 变量控制,而 $setup 变量可以被用户完全控制(如上图 第10行 代码),攻击者完全可以控制网站的安装步骤。
漏洞利用就极其简单了,我们先来看一下 FengCms ,我们直接访问 install/index.php 页面,无视弹出来的警告:
可以看到程序仍然可以继续安装。
我们再来看一下 Simple-Log 的重装利用:
直接post以上数据,即可重装网站数据。
实际上,要修复这一类型的漏洞,我们只要在正确的地方退出程序即可。拿这次的例题举例,我们只需要在检查到非法操作的时候,直接添加退出函数,即可避免漏洞发生。例如使用 die 、 exit 等函数都是可以的,具体修复代码如下:
看完了上述分析,不知道大家是否对 未正确退出程序 导致的攻击有了更加深入的理解,文中用到的 CMS 可以从这里( FengCms 1.32 、 Simple-Log1.6 )下载,当然文中若有不当之处,还望各位斧正。如果你对我们的项目感兴趣,欢迎发送邮件到 hongrisec@gmail.com 联系我们。Day10 的分析文章就到这里,我们最后留了一道CTF题目给大家练手,题目如下:
// index.php <?php include 'config.php'; function stophack($string){ if(is_array($string)){ foreach($string as $key => $val) { $string[$key] = stophack($val); } } else{ $raw = $string; $replace = array("\\","\"","'","/","*","%5C","%22","%27","%2A","~","insert","update","delete","into","load_file $string = str_ireplace($replace, "HongRi", $string); $string = strip_tags($string); if($raw!=$string){ error_log("Hacking attempt."); header('Location: /error/'); } return trim($string); } return trim($string); } } $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("连接失败: "); } if(isset($_GET['id']) && $_GET['id']){ $id = stophack($_GET['id']); $sql = "SELECT * FROM students WHERE id=$id"; $result = $conn->query($sql); if($result->num_rows > 0){ $row = $result->fetch_assoc(); echo '<center><h1>查询结果为:</h1><pre>'.<<<EOF +----+---------+--------------------+-------+ | id | name | email | score | +----+---------+--------------------+-------+ | {$row['id']} | {$row['name']} | {$row['email']} | {$row['score']} | +----+---------+--------------------+-------+</center> EOF; } } else die("你所查询的对象id值不能为空!"); ?>
// config.php <?php $servername = "localhost"; $username = "fire"; $password = "fire"; $dbname = "day10"; ?> # 搭建CTF环境使用的sql语句 create database day10; use day10; create table students ( id int(6) unsigned auto_increment primary key, name varchar(20) not null, email varchar(30) not null, score int(8) unsigned not null ); INSERT INTO students VALUES(1,'Lucia','Lucia@hongri.com',100); INSERT INTO students VALUES(2,'Danny','Danny@hongri.com',59); INSERT INTO students VALUES(3,'Alina','Alina@hongri.com',66); INSERT INTO students VALUES(4,'Jameson','Jameson@hongri.com',13); INSERT INTO students VALUES(5,'Allie','Allie@hongri.com',88); create table flag(flag varchar(30) not null); INSERT INTO flag VALUES('HRCTF{tim3_blind_Sql}');
题解我们会阶段性放出,如果大家有什么好的解法,可以在文章底下留言,祝大家玩的愉快!
本文作者:红日安全团队
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/75196.html