从今天起,结合红日安全写的文章,开始学习代码审计,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会再用一道有相同问题的CTF题来进行巩固。下面开始分析。php
下面咱们看第一题,代码以下:mysql
<?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()的理解,这里写一段简单的代码。sql
<?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题目来加深巩固一下。shell
这道题目也是in_array()函数没有设置第三个参数,致使白名单被绕过,而后被SQL注入。下面咱们具体看一下相关代码。
index.php数组
<?php include 'config.php'; $conn = new mysqli($servername,$username,$password,$dbname); if ($conn->connect_error){ die("链接失败"); } $sql="SELECT COUNT(*) FROM users"; $whitelist = array(); $result = $conn->query($sql); if ($result->num_rows > 0){ $row = $result->fetch_assoc(); $whitelist = range(1,$row['COUNT(*)']); } $id = stop_hack($_GET['id']); $sql = "SELECT * FROM users WHERE id=$id"; if (!in_array($id,$whitelist)){ die("id $id is not in whitelist."); } $result = $conn->query($sql); if ($result->num_rows > 0){ $row = $result->fetch_assoc(); echo "<center><table border='1'>"; foreach ($row as $key=>$value){ echo "<tr><td><center>$key</center></td><br>"; echo "<td><center>$value</center></td></tr><br>"; } echo "</table></center>"; } else{ die($conn->error); } ?>
而后的config.php的相关代码。
config.php安全
<?php $servername = "localhost"; $username = "root"; $password = "XFAICL1314"; $dbname = "day1"; function stop_hack($value){ $pattern = "insert|delete|or|concat|concat_ws|group_concat|join|floor| \/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex| file_put_contents|fwrite|curl|system|eval"; $back_list = explode("|",$pattern); foreach ($back_list as $hack){ if (preg_match("/$hack/i",$value)) { die("$hack detected"); } } return $value; } ?>
而后是搭建CTF使用的sql语句。curl
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}');
用上面代码咱们在本地将环境搭建好。而后开始分析,先看index.php文件代码。再第16行经过$_GET方法接收用户的输入,并用stop_hack()来过滤用户的输入,而后下方直接拼接到sql语句中进行查询。而后再向下看,这里这里用in_array()来进行一个简单的检查,咱们发现它没有设置第三个参数,进行弱类型检查。如今咱们来验证一下,眼见为实。根据咱们上方白名单规则,咱们如今id只能输入1~5。如今咱们输入3来看一下,发现查询到了信息。
如今咱们输入8,它不在白名单中,看看返回什么。
上面是正常的输入,因此白名单是有效的,下面咱们构造payload,好比咱们输入:1'
,发现程序报错,绕过了白名单的检查。能够直接报错注入。
而关于报错注入的函数,大约有四个,分别是:floor()、extractvalue()、updatexml()、exp()
。
虽然绕过了白名单,可是还有过滤函数stop_hack()如今咱们定位到这个函数看看:
发现过滤了一些危险函数,咱们查看后发现,这里没有过滤updatexml()函数,能够用它,可是concat函数被过滤了,咱们须要找到能够替换得函数了。这里咱们使用make_set()函数,它的用法是make_set()函数是先将x转化成二进制,例如: 11的二进制为1011,将二进制顺序颠倒变成1101,每一位数再与后面的字符串相对应,为1的截取,为0的丢弃。以下图:
因此咱们构造payload,获取数据,为了不占用篇幅这里直接是获取到flag的payload。函数
and updatexml(1,make_set(3,'~',(select flag from flag limit 1)),1)
经过这篇文章的讲解,是否是对in_array()理解更深了一些呢?下一篇文章会对filter_var函数缺陷致使的漏洞进行学习和分析,一块儿努力吧!
个人博客即将同步至腾讯云+社区,邀请你们一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1pxmil6lphjna学习