1

我在 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

如果路径是干净的就足够了。

有没有办法编写一个访问父目录的路径,这个简单的测试不会检测到?

4

3 回答 3

2

我建议使用os.path.relpath,它需要一个路径并从给定目录中计算出最简洁的相对路径。这样你只需要测试路径是否以".."

例如。

path = ...
relativePath = os.path.relpath(path)
if relativePath.startswith(".."):
    raise RuntimeError("path escapes static directory")
completePath = "static/" + relativePath

os.readlink如果符号链接是您必须担心的事情,您还可以使用真实路径替换符号链接。

于 2012-12-09T10:49:39.860 回答
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
于 2012-12-09T10:31:30.303 回答
0
..//

这本质上是一回事,但是由于您直接匹配字符串,/../ 因此我添加的字符串不会被检测到并会获取父目录。

于 2012-12-09T10:30:23.513 回答