bandit工具分析
字数 1209 2025-08-27 12:33:23
Bandit工具详细使用指南
1. Bandit简介
Bandit是一个用于检查Python代码安全问题的静态分析工具,它通过以下方式工作:
- 处理源代码文件
- 解析出AST抽象语法树
- 对AST节点运行对应的插件
- 扫描结束后生成安全报告
项目资源:
2. 安装与基本使用
安装
pip3 install bandit
基本扫描命令
bandit -r ./ # 递归扫描当前目录
3. 漏洞检测机制
Bandit通过将内置漏洞库与被检测代码对比来发现安全问题。内置插件位于bandit/plugins目录下。
可检测的漏洞类型:
- 文件权限问题
- 硬编码密钥
- 硬编码临时目录
- 密码隐私设置问题
- 硬编码SQL语句
- 以及其他多种安全问题
4. 自定义漏洞检测
用户可以通过三种方式扩展Bandit的功能:
4.1 编写自定义插件
以app_debug.py插件为例,检测Flask debug模式是否开启:
import bandit
from bandit.core import issue
from bandit.core import test_properties as test
@test.test_id("B201")
@test.checks("Call")
def flask_debug_true(context):
if context.is_module_imported_like("flask"):
if context.call_function_name_qual.endswith(".run"):
if context.check_call_arg_value("debug", "True"):
return bandit.Issue(
severity=bandit.HIGH,
confidence=bandit.MEDIUM,
cwe=issue.Cwe.CODE_INJECTION,
text="A Flask app appears to be run with debug=True, "
"which exposes the Werkzeug debugger and allows "
"the execution of arbitrary code.",
lineno=context.get_lineno_for_call_arg("debug"),
)
关键元素:
@test.test_id("B201"):漏洞编号装饰器(B101-B703)@test.checks("Call"):检测类型(Call/Str/Assert/Exec等)- 使用上下文方法检测特定条件
4.2 imports.py配置文件
检测危险的import语句,定义了B401-B415漏洞:
- 检测可能导致反序列化漏洞的库
- 可扩展为检测特定版本的漏洞库
4.3 calls.py配置文件
检测存在漏洞的调用,定义了B301-B325漏洞:
- 需要同时检测到import和调用
- 匹配格式为
包.方法(如hashlib.md5)
5. 源码分析
5.1 项目结构
git clone https://github.com/PyCQA/bandit
pip3 install -r requirements.txt
5.2 入口点
bandit/cli/main.py中的main()函数
主要参数:
-r/--recursive:递归扫描子目录-t/--tests:指定测试ID-s/--skips:跳过特定测试-f/--format:输出格式(csv/html/json等)
5.3 核心流程
-
初始化:
b_mgr = b_manager.BanditManager( b_conf, args.agg_type, args.debug, profile=profile, verbose=args.verbose, quiet=args.quiet, ignore_nosec=args.ignore_nosec ) -
文件发现:
b_mgr.discover_files(args.targets, args.recursive, args.excluded_paths) -
AST解析:
f_ast = ast.parse(data) generic_visit(f_ast) # 遍历AST节点 -
节点检测:
visit_Import:检测import语句visit_Call:检测函数调用- 其他节点类型有对应的visit方法
6. 实战应用:批量检测GitHub项目
6.1 GitHub搜索API
url = "https://api.github.com/search/repositories?q={}&per_page={}&page={}".format(
keyword, per_page, i
)
注意事项:
- 未认证请求:每分钟最多10次
- 认证请求:每分钟最多30次
6.2 自动化检测脚本
import time
import requests
import json
import os
import datetime
import logging
MAX_NUM = 2 # 最大页数
def getRepItem(keyword, per_page=10):
for i in range(1, MAX_NUM):
starttime = datetime.datetime.now()
url = "https://api.github.com/search/repositories?q={}&per_page={}&page={}".format(
keyword, per_page, i
)
rep = requests.get(url, timeout=5)
items = json.loads(rep.text)['items']
for j in range(len(items)):
rep_url = items[j]['html_url']
cloneRsp(rep_url)
filename = rep_url.split('/')[4]
callBandit(filename)
endtime = datetime.datetime.now()
checkTime((endtime - starttime).seconds)
return
def cloneRsp(url):
logging.info("clone {}".format(url))
os.system('git clone {}'.format(url))
def callBandit(filename):
logging.info("bandit {}".format(filename))
os.system("bandit -r ./{} -f html -o ./{}/scan_{}.html".format(
filename, filename, filename
))
def checkTime(runtime):
logging.info("runtime is {}".format(runtime))
if runtime < 60:
time.sleep(62 - int(runtime))
def main():
getRepItem("cms+language:python")
if __name__ == '__main__':
main()
脚本功能:
- 通过GitHub API搜索项目
- 克隆仓库到本地
- 使用Bandit扫描
- 生成HTML格式报告
- 自动处理API速率限制