对于一个简单的Web服务器脚本,我编写了以下函数来解析文件系统的URL。
def resolve(url):
url = url.lstrip('/')
path = os.path.abspath(os.path.join(os.path.dirname(__file__), url))
return path
以下是__file__
变量C:\projects\resolve.py
的一些示例输出。
/index.html => C:\projects\index.html
/\index.html => C:\index.html
/C:\index.html => C:\index.html
第一个例子很好。 url被解析为脚本目录中的文件。但是,我没想到第二个和第三个例子。由于附加路径被解释为绝对路径,因此它完全忽略脚本文件所在的目录。
这是一种安全风险,因为文件系统上的所有文件都可以访问,而不仅仅是脚本子目录中的文件。为什么Python os.path.join
允许加入绝对路径?如何防止它?
答案 0 :(得分:3)
os.path.join()
不适合不安全的输入,不。绝对的道路完全是故意忽略了它之前的争论;这允许在配置文件中支持绝对路径和相对路径,例如,无需测试输入的路径。只需使用os.path.join(standard_location, config_path)
即可为您做正确的事。
查看Flask's safe_join()
以处理不受信任的文件名:
import posixpath
import os.path
_os_alt_seps = list(sep for sep in [os.path.sep, os.path.altsep]
if sep not in (None, '/'))
def safe_join(directory, filename):
# docstring omitted for brevity
filename = posixpath.normpath(filename)
for sep in _os_alt_seps:
if sep in filename:
raise NotFound()
if os.path.isabs(filename) or \
filename == '..' or \
filename.startswith('../'):
raise NotFound()
return os.path.join(directory, filename)
这使用posixpath
(平台无关的os.path
模块的POSIX实现)来首先规范化URL路径;这将删除所有嵌入的../
或./
路径段,使其成为完全规范化的相对路径或绝对路径。
然后排除/
以外的任何替代分隔符;例如,您不能使用/\index.html
。最后但并非最不重要的是,绝对文件名或相对文件名也是特别禁止的。