Python中少为人知的5个安全陷阱!老男孩python培训机构
老男孩IT教育
行业新闻
2022年2月21日 14:48
Python开发人员在使用标准库和通用框架时,往往都会认为自己的程序、项目非常安全,然而有些特性可能会被开发人员误解或使用,从而在代码中引入严重的安全漏洞,本篇文章总结了5个安全陷阱,请看下文:
Python开发人员在使用标准库和通用框架时,往往都会认为自己的程序、项目非常安全,然而有些特性可能会被开发人员误解或使用,从而在代码中引入严重的安全漏洞,本篇文章总结了5个安全陷阱,请看下文:
1、绝对路径拼接
os.path.join(path,*paths)函数用于将多个文件路径连接成一个组合的路径。第一个参数通常包含了基础路径,而之后的每个参数都被当做组件拼接到基础路径后。
然而,这个函数有一个少有人知的特性。如果拼接的某个路径以/开头,那么包括基础路径在内的所有前缀路径都将被删除,该路径将被视为绝对路径。下面的示例揭示了开发者可能遇到的这个陷阱。
def read_file(request):
filename = request.POST['filename']
file_path = os.path.join("var", "lib", filename)
if file_path.find(".") != -1:
return HttpResponse("Failed!")
with open(file_path) as f:
return HttpResponse(f.read(), content_type='text/plain')
在第3行中,我们使用os.path.join函数将用户输入的文件名构造出目标路径。在第4行中,检查生成的路径是否包含”.“,防止出现路径遍历漏洞。
但是,如果攻击者传入的文件名参数为”/a/b/c.txt“,那么第3行得到的变量file_path会是一个绝对路径(/a/b/c.txt)。即os.path.join会忽略掉”var/lib“部分,攻击者可以不使用“.”字符就读取到任何文件。
2、URL查询参数解析
在Python<3.7中,urllib.parse.parse_qsl函数允许使用“;”和“&”字符作为URL的查询变量的分隔符。有趣的是“;”字符不能被其它语言识别为分隔符。
在下面的例子中,我们将展示为什么这种行为会导致漏洞。假设我们正在运行一个基础设施,其中前端是一个PHP程序,后端则是一个Python程序。
攻击者向PHP前端发送以下的 GET 请求:
GET https://victim.com/?a=1;b=2
PHP前端只识别出一个查询参数“a”,其内容为“1;b=2”。PHP 不把“;”字符作为查询参数的分隔符。现在,前端会将攻击者的请求直接转发给内部的Python程序:
GET https://internal.backend/?a=1;b=2
3、不完整的正则表达式匹配
正则表达式(regex)是大多数Web程序不可或缺的一部分。我们经常能看到它被自定义的Web应用防火墙(WAF,Web Application Firewalls)用来作输入验证,例如检测恶意字符串。在Python 中,re.match和re.search之间有着细微的区别,我们将在下面的代码片段中演示。
def is_sql_injection(request):
pattern = re.compile(r".*(union)|(select).*")
name_to_test = request.GET['name']
if re.search(pattern, name_to_test):
return True
return False
在第2行中,我们定义了一个匹配union或者select的模式,以检测可能的SQL注入。这是一个糟糕的写法,因为你可以轻易地绕过这些黑名单,但我们已经在线上的程序中见过它。在第4行中,函数re.match使用前面定义好的模式,检查第3行中的用户输入内容是否包含这些恶意的值。
然而,与re.search函数不同的是,re.match函数不匹配新行。例如,如果攻击者提交了值aaaaaa \n union select,这个输入就匹配不上正则表达式。因此,检查可以被绕过,失去保护作用。
4、任意的临时文件
tempfile.NamedTemporaryFile函数用于创建具有特定名称的临时文件。但是,prefix(前缀)和 suffix(后缀)参数很容易受到路径遍历攻击。如果攻击者控制了这些参数之一,他就可以在文件系统中的任意位置创建出一个临时文件。下面的示例揭示了开发者可能遇到的一个陷阱。
def touch_tmp_file(request):
id = request.GET['id']
tmp_file = tempfile.NamedTemporaryFile(prefix=id)
return HttpResponse(f"tmp file: {tmp_file} created!", content_type='text/plain')
5、被优化掉的断言
Python支持以优化的方式执行代码。这使代码运行得更快,内存用得更少。当程序被大规模使用,或者可用的资源很少时,这种方法尤其有效。一些预打包的Python程序提供了优化的字节码。
然而,当代码被优化时,所有的assert语句都会被忽略。开发者有时会使用它们来判断代码中的某些条件。例如,如果使用断言来作身份验证检查,则可能导致安全绕过。
def superuser_action(request, user):
assert user.is_super_user
# execute action as super user
在这个例子中,第2行中的assert语句将被忽略,导致非超级用户也可以运行到下一行代码。不推荐使用assert语句进行安全相关的检查,但我们确实在实际的项目中看到过它们。
关于"Python中少为人知的5个安全陷阱!"的话题到这里就结束了,老男孩教育是Python培训领域的专家,2012年就开展了Python培训,是行业较早的Python培训机构,积累了大量的Python培训教学经验,并能全局把控企业用人指标,科学的制定了Python教学课程体系,满足5-8年职业生涯需求,让学员轻松拿下高薪职位!
推荐阅读:
【Python培训机构】学习Python后可以从事哪些工作呢?
