我喜欢用Python编写一个模板系统,它允许包含文件。
例如
This is a template
You can safely include files with safe_include`othertemplate.rst`
你知道,包括文件可能是危险的。例如,如果我在Web应用程序中使用模板系统,允许用户创建自己的模板,他们可能会做类似的事情
I want your passwords: safe_include`/etc/password`
因此,我必须限制将文件包含在例如某个子目录(例如/ home / user / templates)中的文件中,
现在的问题是:如何检查/home/user/templates/includes/inc1.rst是否在/ home / user / templates的子目录中?
以下代码是否可以正常运行?
import os.path
def in_directory(file, directory, allow_symlink = False):
#make both absolute
directory = os.path.abspath(directory)
file = os.path.abspath(file)
#check whether file is a symbolic link, if yes, return false if they are not allowed
if not allow_symlink and os.path.islink(file):
return False
#return true, if the common prefix of both is equal to directory
#e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
return os.path.commonprefix([file, directory]) == directory
就像allow_symlink是False一样,它应该是安全的,我想。如果用户能够创建这样的链接,那么允许符号链接当然会使它不安全。
更新 – 解决方案
如果中间目录是符号链接,上面的代码不起作用。
为了防止这种情况,你必须使用realpath而不是abspath。
UPDATE:添加一个尾部/目录来解决commonprefix()的问题Reorx指出。
这也使得allow_symlink不必要,因为符号链接被扩展到它们的真实目的地
import os.path
def in_directory(file, directory):
#make both absolute
directory = os.path.join(os.path.realpath(directory), '')
file = os.path.realpath(file)
#return true, if the common prefix of both is equal to directory
#e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
return os.path.commonprefix([file, directory]) == directory