从今天起,结合红日安全写的文章,开始学习代码审计,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会再用一道有相同问题的CTF题来进行巩固。下面开始分析。
漏洞分析下面我们看第一题,代码如下:
<?php class Challenge{ const UPLOAD_DIRECTORY = './solutions/'; private $file; private $whitelist; public function __construct($file) { $this->file = $file; $this->whitelist=range(1,24); } public function __destruct() { // TODO: Implement __destruct() method. //这里要特别注意!!! if (in_array($this->file['name'],$this->whitelist)){ move_uploaded_file( $this->file['tmp_name'], self::UPLOAD_DIRECTORY.$this->file['name'] ); } } } $challenge=new Challenge($_FILES['solution']); ?>这一关考察的是任意文件上传漏洞,导致这个漏洞发生的是上方代码中,对in_array()函数使用不规范导致的。这里详细说一下in_array()函数的用法。先看一下PHP手册对这个函数的解释,是检查数组中存在某个值,重点是我圈起来的,如果没有设置第三个参数,那么就使用宽松的检查,问题就出现在这里。
现在看上方代码第12行,这里使用了in_array()函数来检查文件名,但是没有设置第三个参数!,只会进行弱类型比较,不会检查数据类型。比如上面白名单规定,只能上传1~24的文件名,我们上传3shell.php,因为3在白名单中,所以它会将3shell转换成3从而绕过了白名单,达到了任意文件上传的目的。
为了加深对in_array()的理解,这里写一段简单的代码。 <?php $id =3 and 1=1; $whitelist = range(1, 5); if (!in_array($id, $whitelist)) { echo "你想搞事"; } else { echo "你通过了"; } ?>
这里in_array()也是没有设置第三个参数,会进行弱类型比较,会将3 and 1=1转化为3从而绕过了白名单,输出你通过了。当我设置第三个参数为true时,此时会进行强类型检查。所以我们将上文第三行代码修改为:if (!in_array($id, $whitelist,true)),再执行就会输出:“你想搞事”。
现在是不是对in_array()函数有了一个大概的了解呢?那让我们做一道同类型CTF题目来加深巩固一下。 CTF练习
这道题目也是in_array()函数没有设置第三个参数,导致白名单被绕过,然后被SQL注入。下面我们具体看一下相关代码。
index.php
然后的config.php的相关代码。
config.php
然后是搭建CTF使用的sql语句。
create database day1; use day1; create table users ( id int(6) unsigned auto_increment primary key, name varchar(20) not null, email varchar(30) not null, salary int(8) unsigned not null ); INSERT INTO users VALUES(1,'Lucia','Lucia@hongri.com',3000); INSERT INTO users VALUES(2,'Danny','Danny@hongri.com',4500); INSERT INTO users VALUES(3,'Alina','Alina@hongri.com',2700); INSERT INTO users VALUES(4,'Jameson','Jameson@hongri.com',10000); INSERT INTO users VALUES(5,'Allie','Allie@hongri.com',6000); create table flag(flag varchar(30) not null); INSERT INTO flag VALUES('HRCTF{1n0rrY_i3_Vu1n3rab13}'); 题目解析