代码审计:python代码审计汇总(持续更新中)
字数 1588 2025-08-20 18:18:23
Python代码审计与安全开发指南
1. 命令注入漏洞
危险函数列表
os.system()os.popen()subprocess.Popen()platform.popen()commands模块方法pty.spawn()importlib.import_module()
典型漏洞示例
def myserve(request, fullname):
os.system("sudo rm -f %s" % fullname) # 用户可控的fullname可导致命令注入
防御措施
- 避免使用
shell=True参数 - 使用转义函数:
- Python 2.x:
pipes.quote() - Python 3.3+:
shlex.quote()
- Python 2.x:
2. 代码注入漏洞
危险函数
eval()exec()execfile()compile()timeit.timeit()timeit.repeat()
漏洞示例
def eval_test(request, login):
login = eval(login) # 用户可控的login可导致代码执行
防御措施
- 使用
ast.literal_eval()替代eval() - 限制可执行代码范围
- 使用类型转换函数如
int(),float()
3. 不安全的反序列化
危险模块
marshalPyYAML的yaml.load()pickle/cPickleshelvePILUnzip
漏洞示例
import pickle
pickle.loads("cos\nsystem\n(S'uname -a'\ntR.") # 可执行任意命令
防御措施
- 使用
yaml.safe_load()替代yaml.load() - 避免反序列化不可信数据
- 使用JSON等更安全的序列化格式
4. SQL注入
错误用法
def getUsers(user_id):
sql = 'select * from auth_user where id =%s' % user_id
res = cur.execute(sql) # 直接拼接SQL语句
正确用法
args = (id, type)
cur.execute('select id,name from user_table where id = %s and name = %s', args)
防御措施
- 使用参数化查询
- 使用ORM框架
- 避免直接拼接SQL语句
5. 任意文件下载/操作漏洞
危险函数
file()file.save()open()codecs.open()
漏洞示例
def export_task(request, filename):
return HttpResponse(fullname) # 未验证的文件路径可导致任意文件下载
防御措施
- 验证文件路径
- 限制访问目录
- 检查文件类型
6. XXE漏洞
危险模块
xml.dom.*xml.etree.ElementTreexml.sax.*
防御措施
- 禁用外部实体解析
- 使用更安全的XML解析器
- 验证XML输入
7. SSRF漏洞
危险函数
requests.get()urllib.urlopen()urllib2.urlopen()
漏洞示例
url = request.GET['url']
handle = urllib.urlopen(url) # 用户可控的URL可导致SSRF
防御措施
- 验证URL
- 限制访问内网
- 使用白名单机制
8. XSS漏洞
漏洞示例
return HttpResponse('hello %s' % (name)) # 未转义的输出可导致XSS
安全写法
return render_to_response('hello.html', {'name': name})
防御措施
- 对所有输出进行HTML转义
- 使用模板引擎的自动转义功能
- 设置Content Security Policy
9. 直接重定向漏洞
漏洞示例
strDest = request.field("dest")
redirect(strDest) # 未验证的重定向目标
防御措施
- 验证重定向URL
- 使用白名单机制
- 避免使用用户提供的重定向目标
10. 日志伪造漏洞
关注点
logging()函数LOGGER关键字- 敏感信息输出
防御措施
- 避免记录敏感信息
- 对日志内容进行过滤
- 使用安全的日志框架
11. 模板注入(SSTI)
危险函数
render_template_string
漏洞示例
@app.route('/')
def index():
name = request.args.get('name', 'Guest')
return render_template_string('Hello, {{ name }}!', name=name)
攻击示例
http://your-app.com/?name={{ config.__class__.__init__.__globals__['os'].popen('whoami').read() }}
防御策略
- 使用
render_template替代render_template_string - 验证和过滤输入
- 使用ORM框架
- 保持框架和库更新
12. 不安全的随机数
不安全用法
random.randint(0, 100) # 不适用于安全加密用途
安全用法
- Linux/Unix: 使用
/dev/random - Windows: 使用
random.SystemRandom
13. 格式化字符串漏洞
漏洞示例
"My name is %s" % ('jayway', )
"My name is {}".format('jayway')
"My name is %(name)%" % {'name': 'jayway'}
防御措施
- 避免使用用户控制的格式化字符串
- 对输出进行转义
14. 代码审计工具 - Bandit
安装与使用
pip install bandit
bandit -r /path/to/code/ -f html -o report.html
参数说明
-r: 扫描的源码目录-f: 报告格式(html, csv, json等)-o: 输出文件名
总结
Python代码安全审计需要关注多个方面,从命令注入到模板注入,每种漏洞都有其特定的防御策略。开发者应当:
- 了解各种危险函数和模块
- 遵循安全编码实践
- 使用安全工具进行代码审计
- 保持框架和库的更新
- 对所有用户输入进行验证和过滤
通过全面的安全意识和实践,可以显著降低Python应用程序的安全风险。