聊聊php安全之目录遍历和代码注入

目录遍历

目录遍历是指经过身份验证或未经身份验证的用户可以请求并查看或执行 驻留在web应用程序的根目录之前或位于应该限制其目录的文件之外的文件的攻击。
这会导致攻击者能够读取运行web服务器的用户(通常是www数据) 可以访问的任何文件。
如果服务器配置错误的文件权限(非常常见),那么这种攻击可能会进一步加强。

在下面的例子中,脚本直接将一个未经验证/未处理的值传递给include()函数。这意味着脚本会试图包含任何路径/文件名作为参数传递:

不安全的代码示例:

1
2
$file = $_GET['file'];
include($file);

例如,传递/etc/passwd 所有用户可读的文件将返回包含系统中所有用户信息的文件内容:

php-security

根据具体情况,可以通过不同的方式来解决该漏洞。最常见的方法是使用basename()和realpath()函数。

basename()函数只返回给定路径/文件名中的文件名

1
2
Input: ../../../etc/passwd
Output: passwd

realname()函数仅在文件存在且正在运行的脚本对层次结构中的所有目录具有可执行权限的情况下返回规范化的绝对路径名。

1
2
Input: ../../../etc/passwd
Output: /etc/passwd

安全代码示例:

1
2
$file = basename(realpath($_GET['file']));
include($file);

注意- 这将防止目录遍历,但不会影响包含的本地文件。攻击者仍然可以在脚本所在目录中请求文件

现在,当我们请求同一个文件时,我们得到一个空的响应:

php-security

避免列入黑名单

黑名单通常是一种不好的做法,因为有多种方式可以提出相同的请求,而黑客总能找到绕过限制的方法。比如../../../etc/ 也可以写成..%2F..%2F..%2Fetc%2F.如果你需要指定对特定文件的访问权限,请使用白名单。

代码注入/执行

在此漏洞中,攻击者恶意利用包含系统函数/调用的脚本来读取或执行远程服务器上的文件。这与拥有后门shell是同义词。
在这个例子中,脚本使用exec()函数来执行ping命令。但是,主机在通过HTTP GET请求传递时是动态的:

不安全的代码示例:

1
2
3
4
exec('ping -c 4' . $_GET['host'], $output);
echo "<pre>";
print_r($output);
echo "</pre>";

www.baidu.com为例,返回ping命令的输出结果(mac上输入为空):

php-security

这很容易受到代码注入的影响,因为它允许用户通过简单的使用在linux中用来执行多个内联命令的’;’分隔符来将多个命令传递给该函数。
例如,在主机参数中传递以下值www.baidu.com;whoami将返回:

php-security

正如我们所看到的,该脚本执行了ping和whoami命令。

php有两个功能,escapeshellarg()escapeshellcmd(),他有加固的功能。例如exec(),shell_exec(),passthru()system()

escapeshellcmd 转义可以用于执行任意命令的字符串中的任何字符。

通过在他们前面加反斜杠,以下字符被转义:

&#;`|*?~<>^()[]{}$\, \x0A and \xFF
单引号和双引号只有在未配对时才会被转义。

1
2
Input: ping -c 4 wwww.baidu.com;ls -lah
Output: ping -c 4 www.baidu.com\;ls -lah

escapeshellarg在字符串周围添加单引号并转义任何现有的单引号,以便将整个字符串作为单个参数传递给shell命令。

安全代码示例:

1
2
3
4
5
// #1 Restrict multiple commands
exec(escapeshellcmd("ping -c 4 " . $_GET['host']), $output);

// #2 Restrict multiple commands and multiple arguments
exec(escapeshellcmd("ping -c 4 " . escapeshellarg($_GET['host'])), $output);

注意:
在#1中确保用户不能运行多个命令。但是,用户仍然可以使用同一个命令的多个参数。
在#2中,用户被限制传递过关命令和参数。

除了使用这些功能外,还可以创建可接受的命令/参数的白名单。
这些escapeshellcmd()escapeshellarg()功能在不同的操作系统上可能表现不可预知,特别是在windows上。

除非有必要保留,否则强烈建议不要在php配置中使用这些功能,最好是禁用这些功能以避免安全问题。

坚持原创技术分享,您的支持将鼓励我继续创作!