跳转至

黑客与安全技术指南(第4章 代码审计)

php 语言基础

PHP 中的数组是一种用于存储多个值的数据结构。下面是一些关于 PHP 数组的基本用法:

  1. 创建数组:
  2. 使用 array() 函数创建数组:$array = array(value1, value2, ...);
  3. 使用方括号 [] 创建数组:$array = [value1, value2, ...];
  4. 访问数组元素:
  5. 使用方括号加索引访问元素:$element = $array[index];
  6. 注意,PHP 数组的索引可以是整数或字符串。
  7. 修改数组元素:
  8. 使用方括号加索引修改元素:$array[index] = newValue;
  9. 添加新元素:
  10. 使用方括号加索引添加新元素:$array[index] = value;
  11. 如果未指定索引,则新元素将按照数字索引自动分配。
  12. 删除数组元素:
  13. 使用 unset() 函数删除指定索引的元素:unset($array[index]);
  14. 遍历数组:
  15. 使用 foreach 循环遍历数组的所有元素:foreach ($array as $value) { // do something with $value }
  16. 使用 foreach 循环遍历数组的键和值:foreach ($array as $key => $value) { // do something with $key and $value }
  17. 获取数组长度:
  18. 使用 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
可以看到if语句并没有判断$split_values[2],因此成功绕过,进入rename函数。

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 '无法读取文件内容。';
}

常见传参数组

image.png 高危函数表 image.png