我在python中有一些代码检查文件路径是否访问子目录中的文件。 Web服务器可以访问静态文件夹中的文件。
我使用以下代码段:
path = 'static/' + path
try:
if '/../' in path:
raise RuntimeError('/../ in static file path')
f = open(path)
except (RuntimeError, IOError):
app.abort(404)
return
如果路径干净就足够了。
有没有办法编写一个访问父目录的路径,而这个目录不会被这个简单的测试检测到?
答案 0 :(得分:2)
我建议使用os.path.relpath
,它需要一条路径并从给定目录中找出最简洁的相对路径。这样,您只需要测试路径是否以".."
例如
path = ...
relativePath = os.path.relpath(path)
if relativePath.startswith(".."):
raise RuntimeError("path escapes static directory")
completePath = "static/" + relativePath
如果您需要担心sym链接,您还可以使用os.readlink
将实际路径替换为符号链接。
答案 1 :(得分:1)
Flask有一些辅助函数,我认为你可以毫无问题地复制到你的代码中。推荐的语法是:
filename = secure_filename(dirty_filename)
path = os.path.join(upload_folder, filename)
Werkzeug实现secure_filename
并使用此代码清理文件名:
_filename_ascii_strip_re = re.compile(r'[^A-Za-z0-9_.-]')
_windows_device_files = ('CON', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4', 'LPT1',
'LPT2', 'LPT3', 'PRN', 'NUL')
def secure_filename(filename):
r"""Pass it a filename and it will return a secure version of it. This
filename can then safely be stored on a regular file system and passed
to :func:`os.path.join`. The filename returned is an ASCII only string
for maximum portability.
On windows system the function also makes sure that the file is not
named after one of the special device files.
>>> secure_filename("My cool movie.mov")
'My_cool_movie.mov'
>>> secure_filename("../../../etc/passwd")
'etc_passwd'
>>> secure_filename(u'i contain cool \xfcml\xe4uts.txt')
'i_contain_cool_umlauts.txt'
The function might return an empty filename. It's your responsibility
to ensure that the filename is unique and that you generate random
filename if the function returned an empty one.
.. versionadded:: 0.5
:param filename: the filename to secure
"""
if isinstance(filename, unicode):
from unicodedata import normalize
filename = normalize('NFKD', filename).encode('ascii', 'ignore')
for sep in os.path.sep, os.path.altsep:
if sep:
filename = filename.replace(sep, ' ')
filename = str(_filename_ascii_strip_re.sub('', '_'.join(
filename.split()))).strip('._')
# on nt a couple of special files are present in each folder. We
# have to ensure that the target file is not such a filename. In
# this case we prepend an underline
if os.name == 'nt' and filename and \
filename.split('.')[0].upper() in _windows_device_files:
filename = '_' + filename
return filename
答案 2 :(得分:0)
..//
这基本上是相同的,但是因为你直接匹配/../
的字符串
我添加的一个将不会被检测到并将获得父目录。