黑客与安全技术指南(第4章 代码审计)¶
php 语言基础¶
PHP 中的数组是一种用于存储多个值的数据结构。下面是一些关于 PHP 数组的基本用法:
- 创建数组:
- 使用 array() 函数创建数组:
$array = array(value1, value2, ...);
- 使用方括号 [] 创建数组:
$array = [value1, value2, ...];
- 访问数组元素:
- 使用方括号加索引访问元素:
$element = $array[index];
- 注意,PHP 数组的索引可以是整数或字符串。
- 修改数组元素:
- 使用方括号加索引修改元素:
$array[index] = newValue;
- 添加新元素:
- 使用方括号加索引添加新元素:
$array[index] = value;
- 如果未指定索引,则新元素将按照数字索引自动分配。
- 删除数组元素:
- 使用 unset() 函数删除指定索引的元素:
unset($array[index]);
- 遍历数组:
- 使用 foreach 循环遍历数组的所有元素:
foreach ($array as $value) { // do something with $value }
- 使用 foreach 循环遍历数组的键和值:
foreach ($array as $key => $value) { // do something with $key and $value }
- 获取数组长度:
- 使用 count() 函数获取数组的长度:
$length = count($array);
新内置函数¶
preg_replace正则替换函数 preg_match 正则过滤函数 使用foreach来遍历数组并输出键名和值:
<?php
$array = array("apple" => "苹果", "orange" => "橙子", "banana" => "香蕉");
foreach ($array as $key => $value) {
echo "键名: " . $key . ", 值: " . $value . "<br>";
}
?>
键名: apple, 值: 苹果
键名: orange, 值: 橙子
键名: banana, 值: 香蕉
4.4 变量覆盖¶
变量初始化¶
register_global =on 时才会发生
危险函数引发的变量覆盖¶
extract()¶
extract() 是一个 PHP 函数,用于从关联数组中导入变量到当前的符号表中。它的语法如下:
extract(array $array, int $flags = EXTR_OVERWRITE, string $prefix = ' ')
参数说明:
- $array
:要提取变量的关联数组。
- $flags
(可选):指定提取过程中的行为选项,默认值为 EXTR_OVERWRITE
。可以使用以下选项之一:
- EXTR_OVERWRITE
:如果存在同名的变量,则覆盖已有变量。
- EXTR_SKIP
:如果存在同名的变量,则跳过不进行覆盖。
- EXTR_PREFIX_SAME
:如果存在同名的变量,则添加前缀来区分。
- EXTR_PREFIX_ALL
:对所有变量添加前缀。
- EXTR_PREFIX_INVALID
:对非法或数字开头的变量名添加前缀。
- EXTR_IF_EXISTS
:只有当同名变量已经存在时才进行提取。
- EXTR_PREFIX_IF_EXISTS
:只有当同名变量已经存在时才进行提取,并添加前缀。
- $prefix
(可选):指定变量名称的前缀。
以下是 extract()
函数的示例用法:
$data = array(
'name' => 'John',
'age' => 25,
'city' => 'New York'
);
extract($data);
echo $name; // 输出:John
echo $age; // 输出:25
echo $city; // 输出:New York
extract()
函数从关联数组 $data
中提取了变量,并将其作为变量导入到当前的符号表中。可以直接使用提取出的变量 $name
、$age
和 $city
。
array_map()¶
array_map() 是一个 PHP 函数,用于将回调函数应用于给定数组的每个元素,并返回一个新的数组,新数组的元素是原始数组经过回调函数处理后的结果。
array_map() 函数的语法如下:
array_map(callable $callback, array $array1 [, array ...$arrays]): array
其中参数说明为:
- $callback
:一个回调函数,用于对数组元素进行处理。回调函数可以是一个字符串形式的函数名,也可以是一个匿名函数。
- $array1
:要处理的第一个数组。
- $arrays
(可选):要处理的其他数组,可以传入多个数组。
示例用法:
function square($n) {
return $n * $n;
}
$numbers = [1, 2, 3, 4, 5];
$result = array_map('square', $numbers);
print_r($result);
输出结果为:
Array
(
[0] => 1
[1] => 4
[2] => 9
[3] => 16
[4] => 25
)
上述示例中,我们定义了一个名为 square
的函数,用于计算给定数字的平方。然后我们创建了一个包含一些数字的数组 $numbers
。通过调用 array_map('square', $numbers)
,将 square
函数应用于 $numbers
数组的每个元素,得到一个新的数组 $result
,其中每个元素都是原始数组的元素的平方。最后,使用 print_r()
函数打印输出结果。
array_map()
函数的灵活性允许我们使用不同的回调函数来处理数组元素,从而实现各种不同的操作和转换。
4.5 命令执行¶
PHP调用系统命令执行函数 eval() assert () system() exec() shell_exec() passthru() escapeshellcmd()
4.6 前端文件绕过¶
burpsuit 抓包绕过前段过滤 文件头绕过 逻辑漏洞 双重文件名。
xxx.jpg.php
$split_values[0]=××
$split_values[1]=jpg
$split_values[2]=php
rename($user_dat['usrdir'] . “/” . $_FILES[$whichfile]['name'], $user_dat['usrdir'] . "/" . $split_img[0] . "." . strtolower($split_img[1]));
这里会将之前上传的××.jpg.php改为××.jpg。但根据rename函数特性,当二次上传同名文件时,例如××.jpg.php,紧接着会进入流程,尝试被改名为××.jpg,但因为××.jpg已经存在了,所以成功上传了××.jpg.php。
4.7 文件包含¶
以下函数存在文件包含漏洞: include() include_once() require() require_once() fopen() file_get_contents()
WAF 规则绕过 replace()替换规则比较简单的话 可以创写新的拼接实现文件包含。
file_get_contents()
是一个PHP函数,用于获取指定文件的内容并将其作为字符串返回。
file_get_contents()
函数只能用于读取文件内容,而不能用于写入文件或进行其他文件操作。
其基本语法如下:
<?php
file_get_contents(string $filename, bool $use_include_path = false, resource $context = null, int $offset = 0, int $maxlen = -1): string|false
?>
参数说明:
$filename
:要读取的文件名或URL。$use_include_path
(可选):如果设置为true
,则在include路径中查找文件。$context
(可选):可以是一个stream_context_create()
函数创建的资源类型的上下文(例如,用于设置HTTP请求的header)。$offset
(可选):从文件中的偏移量开始读取。$maxlen
(可选):最大读取的字节数。
返回值:
- 若成功,返回文件内容的字符串。
- 若发生错误,返回
false
。
示例用法:
$fileContents = file_get_contents('path/to/file.txt');
if ($fileContents !== false) {
// 读取成功,继续处理文件内容
echo $fileContents;
} else {
// 读取失败,进行错误处理
echo '无法读取文件内容。';
}
常见传参数组
高危函数表