bandit工具分析
本文首发先知社区:https://xz.aliyun.com/t/11341
Bandit是一个用来检查python代码中安全问题的静态分析工具,它会处理各个各个源代码文件,解析出AST抽象语法树,然后对AST节点运行对应的插件,当Bandit扫描结束后会生成安全报告
项目地址:https://github.com/PyCQA/bandit
项目文档:https://bandit.readthedocs.io/en/latest/
安装使用
直接使用的话用pip下载即可
检测存在漏洞的flask项目
bandit -r ./
自定义漏洞检测
在bandit
扫描过程中将漏洞库里的内容与被检测代码相对比,以此来检测漏洞。内置的漏洞检测插件存放在
bandit/plugins
文件夹下,用户也可以构建自己的测试文件来检测自定义的漏洞,方便bandit
的扩展。
现有的bandit漏洞库可以检查文件权限、硬编码密钥、硬编码临时目录、密码未设置隐私、硬编码SQL语句等类型的漏洞
用户可以通过三种方式完成Bandit的自定义漏洞
- 编写自定义漏洞插件
以app_debug.py
插件为例,该插件检测flask服务器是否在生产环境开启了debug
模式
@test.test_id("B201")
是编号装饰器,每个漏洞有特定的编号,在Bandit现有的漏洞库中,编号从B101到B703结束,编号的第一位都是大写字母B,编号第二位将漏洞类型进行了分类
@test.checks("Call")
是类型漏洞,这里的Call
表示漏洞是由函数调用引起的,除此之外还有Str
、Assert
、Exec
等类型
在漏洞检测插件的正文,调用了多个bandit的内置函数,我们利用这些内置函数来编写配置文件和漏洞文件
Bandit内置函数表如下
现在来看app_debug
插件正文就很容易理解了,表示当前节点的上下文环境导入了flask
包,同时调用该节点的限定名后缀为.run
,参数名和参数值debug=True
,如果这些条件都满足,则表示漏洞存在
- 设置imports.py配置文件
imports.py
用于检测可能会发生危险的import语句,定义了bandit
里面B401->B415的漏洞。例如可能会导致python反序列化漏洞的相关库
个人感觉这部分还可以再细分一点,就像safety-db一样检测存在漏洞的特定版本的库
- 设置calls.py配置文件
calls.py
用来检测文件中可能存在漏洞的调用,定义了B301->B325的漏洞,需要检测到漏洞包的导入+漏洞包在正文代码中的调用,需要检测的内容通常由几部分组成,以.
隔开,必须将每部分都进行匹配之后才可以检测出来,以B303中的hashlib.md5
为例
当程序中同时出现import hashlib
和hashlib.md5()
时,bandit
能够检测出漏洞;当程序出现import hashlib
和hashlib.md2()
时不能检测漏洞
源码分析
git clone https://github.com/PyCQA/bandit
安装对应的库文件
入口文件在bandit/cli/main.py
的main()
使用方法如下
跟进main
方法,函数开头进行了项目初始化、获取用户传入的参数,例如我们在前面输入的-r
参数在这里获取
表示递归查找和处理该目录下的文件
拼接形成目前能检测的插件列表,即这一部分
检测插件由两部分:plugin
和blacklist
组成
plugin
即在plugins
文件夹下的插件列表
blacklist
由两部分组成,详情可见bandit/blacklists
文件夹下的calls.py
和imports.py
接下来的代码中继续初始化项目参数,创建重要对象BanditManager
来到discover_files
方法
该方法传入三个参数
- targets 扫描文件或目录
- recursive 是否递归扫描
- excluded_paths 不扫描的后缀、文件、目录
跟进函数之后获取了我们需要扫描的文件
files_list
作为集合存储需要扫描的目标文件列表
excluded_files
作为集合存储不需要扫描的文件列表
回到main.py
,再进入b_mgr.run_tests()
,开始检测漏洞
遍历所有需要检测的文件并进一步操作
进入self._parse_file(fname, fdata, new_files_list)
核心函数
该函数传入三个参数
- fname 检测文件名
- fdata 文件内容
- new_files_list 待检测文件列表
跟进后进入score = self._execute_ast_visitor(fname, fdata, data, nosec_lines)
BanditNodeVisitor
中定义了很多例如visit_Import
、visit_ImportFrom
、visit_Call
、visit_FunctionDef
等等函数,顾名思义就是对各个类型的AST Node执行对应的函数
process
方法中f_ast = ast.parse(data)
解析源文件为AST抽象语法树
在generic_visit(f_ast)
方法中遍历AST节点并对其类型进行对应的检测
以我们前面说到的import
检测为例,这里的检测函数是visit_Import
其实就是把import的包名,以及该节点的一些上下文环境提取出来存放在self.context
中,然后用tester.run_tests
执行Import
节点的检查,如果查出问题就保存起来
遍历完所有需要检测的文件中的AST节点后,最后是输出结果
检测实战
既然要检测当然考虑到批量的情况,这里给出批量检测github上开源项目代码的相关操作流程
例如我们想要搜索python编写的cms,会出现下面这些结果,访问链接为:
我们使用官方API进行请求,根据规则编写API访问链接:https://api.github.com/search/repositories?q=cms+language:python&per_page=10&page=1&sort=updated
- page: 第几页,从1开始(如果小于1,则默认为第1页)
- per_page : 每页多少个项
我们获取到仓库地址之后下载到本地进行扫描
Github API还有访问速率的限制 Github Rate Limit Docs
对于使用基本身份验证、OAuth 或客户端 ID 和密码的请求,我们每分钟最多可以提出 30 个请求。 对于未经身份验证的请求,速率限制允许您每分钟最多提出 10 个请求,考虑到本地对仓库代码进行解析和漏洞检测也需要时间,我们不进行身份验证,每分钟内完成当页内容的漏洞检测
编写一个调用Github API进行仓库下载,并使用bandit
检测的脚本如下
MAX_NUM
限制爬取的页数,getRepItem
传入符合搜索语法的关键字
运行之后就会在clone
的项目文件夹下生成scan_项目名.html
的漏洞检测报告了
参考链接
- https://ericfu.me/bandit-the-python-static-analyzer/
- Python脚本的脆弱性检测研究与实现_刘佩瑶
- https://blog.csdn.net/Next_Second/article/details/78238328
END
建了一个微信的安全交流群,欢迎添加我微信备注进群
,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 😃
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/16295333.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!