编译方式

1
2
和Java和.NET不同,PHP并不存在手动编译的过程,开发人员只要提供PHP源代码
然后PHP会自己把源代码编译为opcode,由Zend引擎(类似于phpstudy)来解析opcode

协议使用

php://input

介绍

1
2
3
php://input是一个可以访问请求的原始数据的只读流。

php://input可以读取http entity body中指定长度的值,

使用时需要结合file_get_contents函数

1
变量 = file_get_contents("php://input")

缺点

1
无法读取Content-Type为multipart/form-data的POST数据

函数使用

@符号

1
2
@符号是PHP的错误控制操作符,在函数的前面添加@符号时,将不会回显报错信息
也可以用在表达式中

可变函数

1
2
PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号()
PHP 将寻找与变量的值同名的函数,并且尝试执行它。
1
可变函数可以用来实现包括回调函数,函数表在内的一些用途

include()

文件包含时如果发生报错,仍会执行脚本

如果需要包含一个文件时,可用越级符号跳到上一级文件

1
2
3
/index.php?file=index.php../../windows/win.ini

/index.php?file=index.php/../../windows/win.ini

include_once()

如果文件的代码已经被包含了,就不会再包含

将会优先查询一次已加载的文件列表确认是否存在

require()

文件包含是如果发生报错,会停止执行脚本

require_once()

如果文件的代码已经被包含了,就不会再包含

将会优先查询一次已加载的文件列表确认是否存在

assert()

断言函数自PHP 8删除,可以传入一个字符串用于执行php代码

如果需要执行多个php代码时,可使用or关键字

1
assert('phpinfo() or system("ls")')

preg_replace()

传入的模式形参$pattern中存在/e时,就会将第二个参数$replacement作为PHP代码执行

第三个参数$subject得保证符合$pattern的要求才能执行命令

1
preg_replace("/abc/e",PHP代码,"abcd")

变量使用

全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$_GET

$_POST

$_REQUEST

$_SERVER

$_ENV

$_FILE

$_COOKIE

$_SESSION

$GLOBALS

$http_raw_post_data

介绍

1
2
3
是PHP内置的一个全局变量,在PHP无法识别的Content-Type时,将POST的数据原样填入该变量中

在POST请求的情况下,php://input不需要依赖php.ini配置,比$http_raw_post_data更适合获取请求内容

使用条件

1
php.ini中设置 always_ppulate_raw_post_data = on

使用

1
2
通过赋值给其他变量,或者是直接获取该变量的内容即可操作POST的数据内容
变量 = $http_raw_post_data

缺点

1
无法读取Content-Type为multipart/form-data的POST数据

逻辑特性

0e MD5

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
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
s214587387a 0e848240448830537924465865611904
s214587387a 0e848240448830537924465865611904
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s1885207154a 0e509367213418206700842008763514
s1502113478a 0e861580163291561247404381396064
s1885207154a 0e509367213418206700842008763514
s1836677006a 0e481036490867661113260034900752
s155964671a 0e342768416822451524974117254469
s1184209335a 0e072485820392773389523109082030
s1665632922a e731198061491163073197128363787
s1502113478a 0e861580163291561247404381396064
s1836677006a e481036490867661113260034900752
s1091221200a 0e940624217856561557816327384675
s155964671a 0e342768416822451524974117254469
s1502113478a 0e861580163291561247404381396064
s155964671a 0e342768416822451524974117254469
s1665632922a 0e731198061491163073197128363787
s155964671a 0e342768416822451524974117254469
s1091221200a 0e940624217856561557816327384675
s1836677006a 0e481036490867661113260034900752
s1885207154a 0e509367213418206700842008763514
s532378020a 0e220463095855511507588041205815
s878926199a 0e545993274517709034328855841020
s1091221200a 0e940624217856561557816327384675
s214587387a 0e848240448830537924465865611904
s1502113478a 0e861580163291561247404381396064
s1091221200a 0e940624217856561557816327384675
s1665632922a 0e731198061491163073197128363787
s1885207154a 0e509367213418206700842008763514
s1836677006a 0e481036490867661113260034900752
s1665632922a 0e731198061491163073197128363787
s878926199a 0e545993274517709034328855841020

科学计数法

使用科学计数法时,$a的值为9e9,可使以下if语句为真(值很大且位数小)

1
intval($a) > 1000000 && strlen($a) <= 3

短标签绕过

如果php无法使用时,可以采用短标签

1
<?=代码;?>

数组传输

如果要在GET或POST直接传输一个一维数组

1
2
3
数组名[]=值1&数组名[]=值2

数组名[下标]=值1&数组名[下标]=值2

如果要在GET或POST直接传输一个二维数组

1
数组名['键1']=值1&数组名['键2']=值2

如果是要传入空数组时

1
数组名[]=

array_search()绕过

对于一个数值型的数组,如果需要匹配的内容为字符串时,首先会将需要匹配的字符串转换为数字0

之后在数组中匹配的就是0,返回对应的下标或者键

is_numeric()绕过

1
is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。
1
可使用数字的十六进制绕过,需要在前面添加0X
1
先将一个数字添加一个字符a,然后将其用引号引起来。

json_decode

如果值为数字,且需要让其解释为字符串时,必须使用引号括起来

当传入的键值对中值为数组类型时,需要使用[]中括号引起来,而不是花括号

getReailFileType

当文件的头部含有GIF89a时(GIF必须大写),可以绕过该函数检测

漏洞

PHP 5.5.9 数组整数溢出,重排序

当数组为九位16机制数时,会溢出,等同于重新排序,16的8次方即4294967296在逻辑上等同于下标0;

1
2
3
stuff[4294967296]=admin&stuff[1]=user
等同于
stuff[0]=admin&stuff[1]=user