PHP代码审计01之in_array()函数缺陷
前言
从今天起,结合红日安全写的文章,开始学习代码审计,题目均来自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
<?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语句。
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函数缺陷导致的漏洞进行学习和分析,一起努力吧!
PHP代码审计01之in_array()函数缺陷的更多相关文章
- PHP代码审计02之filter_var()函数缺陷
前言 根据红日安全写的文章,学习PHP代码审计审计的第二节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会有一道CTF题目来进行巩固,外加一个实例来深入分析,想了 ...
- PHP-Audit-Labs-Day1 - in_array函数缺陷
函数缺陷原理分析 先看一段简单的源代码 class Challenge{ const UPLOAD_DIRECTORY = './solutions/'; private $file; private ...
- PHP代码审计04之strpos函数使用不当
前言 根据红日安全写的文章,学习PHP代码审计的第四节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一个实例来加深巩固,这是之前写的,有兴趣可以去看看: PHP代码 ...
- 代码审计学习01-in_array() 函数缺陷
一.开始代码审计之旅 01 从今天起,学习代码审计了,这篇文章就叫代码审计01吧,题目来自 PHP SECURITY CALENDAR 2017 的第一题,结合 红日安全 写的文章,开始吧. 二.先看 ...
- 安鸾CTF Writeup PHP代码审计01
PHP代码审计 01 题目URL:http://www.whalwl.xyz:8017 提示:源代码有泄露 既然提示有源代码泄露,我们就先扫描一遍. 精选CTF专用字典: https://github ...
- in_array函数的第三个参数 strict
看段代码 <?php $array = array('testing',0,'name'); var_dump($array); var_dump(in_array('foo', $array) ...
- php -- in_array函数
in_array 检查数组中是否存在某个值 说明 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ...
- PHP使用in_array函数检查数组中是否存在某个值
PHP使用 in_array() 函数检查数组中是否存在某个值,如果存在则返回 TRUE ,否则返回 FALSE. bool in_array( mixed needle, array array [ ...
- 转 PHP in_array() 函数
实例 在数组中搜索值 "Glenn" ,并输出一些文本: <?php $people = array("Bill", "Steve", ...
随机推荐
- latex三种标准文类book, report, article的章节命令与层次深度
Latex有三种标准文类:book, report, article. 每种文类的章节命令和层次深度如下: 三种标准文类的章节命令与层次深度 层次深度 层次名 book report article ...
- P2607 [ZJOI2008]骑士 基环树,树dp;
P2607 [ZJOI2008]骑士 本题本质上就是树dp,和没有上司的舞会差不多,只不过多了一个对基环树的处理. #include<iostream> #include<cstri ...
- win环境下安装配置openCV-4.3.0
win环境下安装openCV-4.3.0 首先下载 推荐国内镜像 官网太太太慢了 附上 下载地址 下载之后打开exe解压到目录都是常规操作 环境变量的配置 依次打开到系统变量的path 新建一个路径为 ...
- Element UI - DatePicker 自定义日期选择期间
<el-date-picker v-else v-model="searchForm.data_Selected" type="daterange" un ...
- 洛谷 P4995 跳跳!
思路 贪心 从大到小排序,然后反复横跳,记录两个指针 \(l=1, r=n\),从 \(1\) 跳到 \(n\),再从 \(n\) 跳到 \(2\),然后从 \(2\) 跳到 \(n - 1\)--, ...
- ORA-01804报错
报错Error while trying to retrieve text for error ORA-01804 环境变量有配https://blog.csdn.net/zklth/article/ ...
- 常用注解@Intdef与@Stringdef
1.优点 可以代替枚举,静态常量,可以让注解只在代码中存在,编译后就删除,可以省内存. 2.@IntDef 2.1 官网 https://developer.android.com/reference ...
- 设计模式(多个if的处理)
使用场景 如果在代码中出现大量if判断,再执行一些比较复杂的业务操作,类似于以下情况. @Test void test() { String str = "A"; if (str. ...
- 【Gin-API系列】守护进程和平滑重启(八)
生产环境的API服务我们都会部署在Linux服务器上,为了不受终端状态的影响,启动服务的时候会让服务在后台运行.那么如何让服务在后台运行呢,目前有2种常见的方法. 1.nohub 运行 表示忽略SIG ...
- 用 Shader 写个完美的波浪
前言 皮皮最近接到了一个小需求: 美术小姐姐:皮皮皮皮,你能不能做奶茶? 我:??? 美术小姐姐:就是那种,奶茶的轮廓加上动态水波纹~