4

我正在编写一个小型只读类似 FTP 的服务器。客户说“给我那个文件”然后我​​的服务器发送它。

是否有任何标准方法(库函数?!?)来确保请求的文件不是“../../../../../etc/passwd”或任何其他坏事?如果我可以将所有查询限制在一个目录(及其子目录)中,那就太好了。

谢谢!

4

6 回答 6

18

Chroot 可能是最好的方法,但您可以使用它realpath(3)来确定给定文件名的规范路径。从手册页:

 char *realpath(const char *file_name, char *resolved_name);

realpath() 函数解析所有符号链接、额外的“/”字符以及文件名中对 /./ 和 /../ 的引用,并将生成的绝对路径名复制到解析后的名称所引用的内存中。resolve_name 参数必须引用能够存储至少 PATH_MAX 个字符的缓冲区。

从那里您可以以您喜欢的任何其他方式限制请求。

于 2009-06-12T01:51:12.433 回答
5

也看看chroot

于 2009-06-11T23:50:54.220 回答
3

虽然这并不完美,但您可以在特定用户/组下运行您的 ftp 服务器,并且只允许该用户/组的某些目录。但是,这可能不是您正在寻找的。

您还可以拥有用户可以访问的目录白名单,以及他们尝试访问的任何其他目录,您根本不允许(因此,基本上是建立您自己的权限)。

我个人更喜欢前者,因为操作系统已经为您完成了这项工作。

于 2009-06-11T23:44:50.787 回答
1

我不知道有一个标准库可以做到这一点。

你可以试试:

  1. 将运行服务器的 unix 用户的权限设置为仅对某个目录具有读/写权限。(可能使用 PAM、chroot 环境或使用标准 unix 用户/组权限)

  2. 您可以设计您的程序,使其仅接受绝对路径(在 unix 中,路径以“/”开头)。这样,您可以检查以确保它是有效路径 - 例如,禁止任何具有字符串“..”的路径

编辑:

来自彼得:看起来有一个库函数realpath()可以帮助上面的#2。

于 2009-06-11T23:50:25.873 回答
1

获取根 (/) 目录的 inode 和服务目录(例如 /ftp/pub)的 inode。对于他们请求的文件,请确保:

  1. 文件存在。
  2. 文件的父级(在文件路径上使用多个“/..”访问)在访问根目录 inode 之前先命中服务目录 inode。

您可以使用stat查找任何目录的inode。将它放在一个函数中,并在提供文件之前调用它。

当然,使用具有适当权限的用户/组也可以。

于 2009-06-12T00:00:02.200 回答
0

在 Windows 中,我会做类似的事情(尽管仍然适用于任何操作系统):

  1. 用户请求文件
  2. 服务器找到文件
  3. 服务器检查 path_to_file 是否以“C:/SomeFolderWithFiles/”开头
  4. 完成交易
于 2009-06-12T00:04:50.597 回答