python安全问题
字数 915 2025-08-22 12:22:37

Python 安全最佳实践指南

1. 断言(assert)的安全隐患

1.1 断言的主要安全问题

  • 运行时被忽略:使用 python -O 优化模式运行时,所有 assert 语句会被跳过
  • 不适用于异常处理:不能替代正式的错误处理机制
  • 敏感信息泄露:可能暴露内部状态、系统路径或错误消息

1.2 安全替代方案

# 不安全方式
assert user == "admin" and password == "secure_password", "Authentication failed!"

# 安全替代方案
if not (user == "admin" and password == "secure_password"):
    raise ValueError("Authentication failed!")
  • 使用显式条件检查和异常处理
  • 实现安全的日志记录机制
  • 对外部输入进行严格验证

2. 目录创建的安全问题

2.1 权限问题

import os

# Python 3.6+ 行为
os.makedirs("a/b/c", mode=0o700)  # a:755, b:755, c:700

# Python 2.7 行为
os.makedirs("a/b/c", mode=0o700)  # 所有目录:700

2.2 条件竞争风险

dir_path = "/tmp/sensitive_data"
os.makedirs(dir_path)  # 临时创建
# 在此时间窗口内存在风险
os.chmod(dir_path, 0o700)  # 事后设置权限

2.3 路径遍历攻击

def create_user_dir(username):
    dir_path = f"/home/{username}/data"  # 危险:未验证输入
    os.makedirs(dir_path)
    
create_user_dir("../../etc")  # 攻击:在/etc下创建目录

3. 路径拼接的安全问题

3.1 路径遍历攻击

import os

def save_file(upload_dir, filename):
    file_path = os.path.join(upload_dir, filename)  # 危险拼接
    with open(file_path, 'w') as f:
        f.write("This is a test file.")
        
save_file("/uploads", "../../etc/passwd")  # 攻击:覆盖系统文件

3.2 符号链接攻击

  • 攻击者可能创建符号链接指向敏感文件
  • 应用程序错误信任这些符号链接会导致安全问题

3.3 绝对路径覆盖

file_path = os.path.join("/safe/directory", "/etc/passwd")
print(file_path)  # 输出: /etc/passwd (忽略前面路径)

4. 临时文件安全问题

import tempfile
import os

id = "/../tmp/test"  # 恶意输入
tmp_file = tempfile.NamedTemporaryFile(prefix=id, delete=False)
file_name = tmp_file.name  # 可能创建在/var/www/test_zdllj17
tmp_file.close()

5. Extended Zip Slip 攻击

5.1 基本攻击方式

import zipfile

def extract_zip(zip_file, extract_to):
    with zipfile.ZipFile(zip_file, 'r') as zf:
        zf.extractall(extract_to)  # 直接解压所有文件(危险)
        
# 压缩包中包含"../../etc/passwd"等恶意路径

5.2 后缀检验绕过

def extract_html(request):
    filename = request.FILES["filename"]
    zf = zipfile.ZipFile(filename.temporary_file_path(), "r")
    for entry in zf.namelist():
        if entry.endswith(".html"):  # 仅检查后缀
            file_content = zf.read(entry)
            with open(entry, "wb") as fp:  # 仍可能路径遍历
                fp.write(file_content)
    zf.close()

6. 正则表达式绕过

6.1 re.search vs re.match

import re

def is_sql_injection(test_str):
    pattern = re.compile(r".*(union)|(select).*")
    return bool(re.search(pattern, test_str))  # 扫描整个字符串

def is_sql_injection_match(test_str):
    pattern = re.compile(r".*(union)|(select).*")
    return bool(re.match(pattern, test_str))  # 仅从开头匹配

test_a = "union xxxasd"
test_b = "xxxasd \n union ASDSDFF"

# re.search 结果
is_sql_injection(test_a)  # True
is_sql_injection(test_b)  # True

# re.match 结果
is_sql_injection_match(test_a)  # True
is_sql_injection_match(test_b)  # False

6.2 标志位影响

def is_sql_injection_match_fix(test_str):
    pattern = r".*(union)|(select).*"
    return bool(re.match(pattern, test_str, re.DOTALL))  # 匹配换行符

is_sql_injection_match_fix(test_b)  # True (之前为False)

7. Unicode编码安全问题

7.1 Unicode标准化绕过

from unicodedata import normalize
from django.utils.html import escape

user_input = escape(request.GET["p"])  # 转义HTML
normalized = normalize("NFKC", user_input)  # %EF%B9%A4 -> <
# 可能导致XSS绕过

7.2 Unicode大小写问题

email = request.GET["email"]
result = User.objects.filter(email__exact=email.upper()).first()
# foo@mıx.com -> FOO@MIX.COM
# foo@mix.com -> FOO@MIX.COM
# 可能导致账户枚举攻击

8. 反序列化安全

  • pickle:存在代码执行风险,不应反序列化不可信数据
  • pyyaml:同样存在安全风险,需谨慎处理

9. pip包管理安全

9.1 使用可信源

pip install --index-url=https://pypi.org/simple <package>

9.2 验证包完整性

pip install --require-hashes -r requirements.txt

requirements.txt 示例:

package==1.0.0 --hash=sha256:hashvalue

9.3 更新策略

  • 非必要不更新,防止供应链攻击
  • 确需更新时,验证新版本的安全性和来源

10. 总结与最佳实践

  1. 避免使用assert进行安全检查:改用显式条件检查
  2. 安全创建目录
    • 正确设置权限
    • 验证输入路径
    • 避免条件竞争
  3. 安全路径处理
    • 规范化路径
    • 检查路径遍历
    • 处理符号链接
  4. 安全解压文件
    • 验证压缩包内容
    • 限制解压路径
  5. 正则表达式安全
    • 理解search/match区别
    • 谨慎使用标志位
  6. 编码安全
    • 注意Unicode标准化
    • 处理大小写转换
  7. 反序列化
    • 避免反序列化不可信数据
  8. pip安全
    • 使用可信源
    • 验证包完整性
    • 谨慎更新

通过遵循这些最佳实践,可以显著提高Python应用程序的安全性,减少潜在的安全漏洞。

Python 安全最佳实践指南 1. 断言(assert)的安全隐患 1.1 断言的主要安全问题 运行时被忽略 :使用 python -O 优化模式运行时,所有 assert 语句会被跳过 不适用于异常处理 :不能替代正式的错误处理机制 敏感信息泄露 :可能暴露内部状态、系统路径或错误消息 1.2 安全替代方案 使用显式条件检查和异常处理 实现安全的日志记录机制 对外部输入进行严格验证 2. 目录创建的安全问题 2.1 权限问题 2.2 条件竞争风险 2.3 路径遍历攻击 3. 路径拼接的安全问题 3.1 路径遍历攻击 3.2 符号链接攻击 攻击者可能创建符号链接指向敏感文件 应用程序错误信任这些符号链接会导致安全问题 3.3 绝对路径覆盖 4. 临时文件安全问题 5. Extended Zip Slip 攻击 5.1 基本攻击方式 5.2 后缀检验绕过 6. 正则表达式绕过 6.1 re.search vs re.match 6.2 标志位影响 7. Unicode编码安全问题 7.1 Unicode标准化绕过 7.2 Unicode大小写问题 8. 反序列化安全 pickle :存在代码执行风险,不应反序列化不可信数据 pyyaml :同样存在安全风险,需谨慎处理 9. pip包管理安全 9.1 使用可信源 9.2 验证包完整性 requirements.txt 示例: 9.3 更新策略 非必要不更新,防止供应链攻击 确需更新时,验证新版本的安全性和来源 10. 总结与最佳实践 避免使用assert进行安全检查 :改用显式条件检查 安全创建目录 : 正确设置权限 验证输入路径 避免条件竞争 安全路径处理 : 规范化路径 检查路径遍历 处理符号链接 安全解压文件 : 验证压缩包内容 限制解压路径 正则表达式安全 : 理解search/match区别 谨慎使用标志位 编码安全 : 注意Unicode标准化 处理大小写转换 反序列化 : 避免反序列化不可信数据 pip安全 : 使用可信源 验证包完整性 谨慎更新 通过遵循这些最佳实践,可以显著提高Python应用程序的安全性,减少潜在的安全漏洞。