我有一个文件浏览器应用程序,它将目录及其内容公开给用户。
我想清理用户输入,这是一个文件路径,因此它不允许绝对路径,如'/ tmp /'和相对路径,如'../../ etc'
是否有跨平台执行此操作的python函数?
答案 0 :(得分:10)
对于那些寻找摆脱" A /./ B" - > " A / B和" A / B /../ C" - > " A / C"在路径中。
您可以使用os.path.normpath
。
答案 1 :(得分:4)
我对任何可用的消毒路径方法都不满意,所以我写了自己的,相对全面的路径消毒剂。这适用于从公共端点(http上传,REST端点等)获取输入,并确保如果将数据保存在生成的文件路径中,则不会损坏您的系统**。 (注意:此代码针对Python 3+,您可能需要进行一些更改才能使其在2.x上运行)
* 不保证!如果没有彻底检查,请不要依赖此代码。
** 再一次,没有保证!您仍然可以做一些疯狂的事情,并将* nix系统上的根路径设置为/dev/
或/bin/
或类似的东西。不要那样做。 Windows上也存在一些可能导致损坏的边缘情况(例如设备文件名),您可以检查secure_filename
的{{1}} werkzeug
方法,以便在处理时有一个良好的开端如果你的目标是Windows,请使用这些。
utils
功能,了解执行此操作的位置。确保根路径的值来自您自己的配置,而不是来自用户的输入!get_root_path
。您可以选择在make_valid_file_path
参数中传递子目录路径。这是根路径下面的路径,可以来自用户输入。您可以选择在path
参数中传递文件名,这也可以来自用户输入。您传递的文件名中的任何路径信息都不会用于确定文件的路径,而是将其展平为文件名的有效安全组件。
filename
路径组件以获取文件的最终路径。好的,有足够的警告和描述,这是代码:
os.path.join
答案 2 :(得分:0)
这将阻止用户输入诸如../../../../etc/shadow
之类的文件名,但也将不允许文件位于basedir
以下的子目录中:
from pathlib import Path
test_path = (Path(basedir) / user_input).resolve()
if test_path.parent != Path(basedir).resolve():
raise Exception(f"Filename {test_path} is not in {Path(basedir)} directory")
如果要允许basedir
下的子目录:
if not Path(basedir).resolve() in test_path.resolve().parents:
raise Exception(f"Filename {test_path} is not in {Path(basedir)} directory")
答案 3 :(得分:0)
我最终在这里寻找一种处理我的用例的最终方法,并最终编写了自己的用例。我需要的是采取一种方法,将其强制纳入CWD。这是针对正在处理已挂载文件的CI系统的。
import java.util.*;
public class Test {
static Scanner input = new Scanner(System.in);
static double y;
public static void main(String[] args) {
double x = someMethod(5);
}
private static double someMethod(int nr) {
try {
y = input.nextDouble();
} catch (InputMismatchException e) {System.out.println("Type in a double");}
return y + nr;
}
}
就我而言,我不想引发异常。我只想强迫给定的任何路径都将成为CWD中的绝对路径。
测试:
def relative_path(the_path: str) -> str:
'''
Force the spec path to be relative to the CI workspace
Sandboxes the path so that you can't escape out of CWD
'''
# Make the path absolute
the_path = os.path.abspath(the_path)
# If it started with a . it'll now be /${PWD}/
# We'll get the path relative to cwd
if the_path.startswith(os.getcwd()):
the_path = '{}{}'.format(os.sep, os.path.relpath(the_path))
# Prepend the path with . and it'll now be ./the/path
the_path = '.{}'.format(the_path)
return the_path
答案 4 :(得分:0)
这是对@mneil 解决方案的改进,使用了relpath
的秘密第二个参数:
import os.path
def sanitize_path(path):
"""
Sanitize a path against directory traversals
>>> sanitize_path('../test')
'test'
>>> sanitize_path('../../test')
'test'
>>> sanitize_path('../../abc/../test')
'test'
>>> sanitize_path('../../abc/../test/fixtures')
'test/fixtures'
>>> sanitize_path('../../abc/../.test/fixtures')
'.test/fixtures'
>>> sanitize_path('/test/foo')
'test/foo'
>>> sanitize_path('./test/bar')
'test/bar'
>>> sanitize_path('.test/baz')
'.test/baz'
>>> sanitize_path('qux')
'qux'
"""
# - pretending to chroot to the current directory
# - cancelling all redundant paths (/.. = /)
# - making the path relative
return os.path.relpath(os.path.normpath(os.path.join("/", path)), "/")
if __name__ == '__main__':
import doctest
doctest.testmod()
答案 5 :(得分:-1)
也许不仅仅是清理路径(黑名单),您只能允许(白名单)有效路径。
python在os.path
中提供了各种工具,以独立的方式执行此操作