强盗工具分析

admin 2022年6月14日07:50:55评论18 views字数 6466阅读21分33秒阅读模式

Bandit 是安全使用 python 中的一个问题的分析,它会处理代码后续结果源代码安全工具文件,解析出 AST 分支树运行的,当 Bandit 扫描生成生成报告

项目地址:https://github.com/PyCQA/bandit

项目文档:https://bandit.readthedocs.io/en/latest/

安装使用

直接使用的话用pip下载智能

pip3 安装强盗

强盗工具分析

检测存在漏洞的烧瓶项目
bandit -r ./

强盗工具分析

自定义漏洞检测

bandit利用漏洞库的内容被检测比,并来检测漏洞。编造的检测代码
bandit/plugins也可以在文件夹中扫描,用户可以自己的测试文件来检测漏洞,方便检测漏洞。bandit的扩展。

现有的bandit漏洞库可以检查文件的隐私权限、硬件编码、硬件临时编码、密码未设置、编码SQL语句等类型的漏洞

可以在bandit -h查看
强盗工具分析

用户可以通过完成方式完成 Bandit 的自定义漏洞

写自定义插件

app_debug.py插件为例,该插件检测flask服务器是否在生产环境开启debug模式

bandit.core导入bandit bandit.core 导入 问题import test_properties作为测试     @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 以(“.run” 结尾:如果上下文check_call_arg_value ( "debug" , "True" ):返回强盗问题严重性=强盗


HIGH
信心=强盗中等
cwe =问题CODE_INJECTION ,
text = "一个 Flask 应用程序似乎在 debug=True 的情况下运行,"
"这会暴露 Werkzeug 调试器并允许 "
"执行任意代码。" ,
lineno =上下文get_lineno_for_call_arg “调试” ),

@test.test_id("B201")是编号的各个漏洞有特定的编号,Bandit 的库中结束,到B101,中结束了编号的类型,从编号的第二位进行了B101,B,编号的编号为70

@test.checks("Call")是类型漏洞,这里的Call表示漏洞是由函数调用引发的,除此之外还有、、Str等类型AssertExec

在漏洞检测插件的正文,调用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 hashlibhashlib.md5()时,bandit能够检测出漏洞;当程序中出现import hashlibhashlib.md2()时不能检测漏洞

根本分析

git clone https://github.com/PyCQA/bandit

安装的库文件

pip3 install -r requirements.txt

入口文件bandit/cli/main.pymain()
使用方法如下

usage: main.py [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]               [-p PROFILE] [-t TESTS] [-s SKIPS]               [-l | --severity-level {all,low,medium,high}]               [-i | --confidence-level {all,low,medium,high}]               [-f {csv,custom,html,json,screen,txt,xml,yaml}]               [--msg-template MSG_TEMPLATE] [-o [OUTPUT_FILE]] [-v] [-d] [-q]               [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]               [--ini INI_PATH] [--exit-zero] [--version]               [targets [targets ...]]

在接下来main的方法中,在活动活动中进行了初始化、获取用户参数,例如前面的输入-r获取参数

解析器add_argument ( 
"-r" ,
"--recursive" ,
dest = "recursive" ,
action = "store_true" ,
help = "在子目录中查找和处理文件" ,
)

表示文件的搜索和处理该下的目录

plugin_info  =  [ 
f "{a[0]} t {a[1].name}" for a in extension_mgr plugins_by_id items ()
]
blacklist_info = []
for a in extension_mgr 黑名单items ():
for b in a [ 1 ]:
blacklist_info 附加( "{} t {}" .格式( b [ "id" ], b[ “名称” ]))
plugin_list = " nt " 加入排序设置plugin_info + blacklist_info )))

创作的作品可以 两个部分组成

强盗工具分析

pluginblacklist

plugin即在plugins文件夹下的插件列表

blacklist由两部分组成,详情可见bandit/blacklists文件夹下的calls.pyimports.py

的代码中继续初始化项目参数,创建重要的输入对象BanditManager

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 ,
)

discover_files方法

b_mgr discover_files ( args.targets , args.recursive ,  args.excluded_pa ths ) _ _ _  _ _


该方法三个参数

目标扫描文件或目录

递归是否逻辑扫描

exclude_paths 不能扫描的后缀、文件、目录

强盗工具分析

后续的活动 获取我们需要的扫描文件

for  fname  in  targets : 
# 如果这是一个目录并且设置了递归,
如果是 os则查找所有文件路径isdir ( fname ):
如果 递归
new_files new_excluded = _get_files_from_dir (
fname
included_globs = included_globs
excluded_pa th_strings = exclude_path_globs ) files_list 更新new_files excluded_files 更新


新排除

files_list作为集合存储需要扫描的目标文件列表

excluded_files作为集合存储不需要扫描的文件列表

回到main.py,再进入b_mgr.run_tests(),开始检测漏洞

全部需要检测的文件并进一步操作

对于 count  fname  in  enumerate ( files ): 
LOG 调试“正在处理文件:%s fname
尝试
如果 fname == "-"
open_fd = os fdopen ( sys . stdin . fileno (), "rb" , 0 )
fdata = io . BytesIO ( open_fd . read ())
new_files_list = [
"<stdin>" if x == "-" else x for x in new_files_list
]
self _parse_file ("<stdin>" , fdata , new_files_list )
else :
with open ( fname , "rb" ) as fdata :
self _parse_file ( fname , fdata , new_files_list )
除了 OSError e :
self 跳过附加(( fname , e . strerror ))
new_files_list 删除( fname )

进入self._parse_file(fname, fdata, new_files_list)核心功能

该函数三个参数

fname 检测文件名

fdata文件内容

new_files_list 待检测文件列表

后续进入score = self._execute_ast_visitor(fname, fdata, data, nosec_lines)

def  _execute_ast_visitor ( self ,  fname ,  fdata ,  data ,  nosec_lines ): 
"""对每个文件执行 AST 解析 :param fname: 被解析的文件名 :param data: 原始文件内容 :param lines: 要处理的代码行数 :return: 累计测试分数 """
score = []
res = b_node_visitor . BanditNodeVisitor (
fname ,
fdata
self.b_ma self.b_ts
self.debug nosec_l ines
self.metrics ) _ _ _ _
_ _ _


分数 = res 处理数据
自我结果扩展res.tester.results 返回分数_ _ _ _

BanditNodeVisitor中定义的函数,例如、、等等,很多visit_Import名思义义就是对特定类型的任务执行的 AST 节点执行visit_ImportFromvisit_Callvisit_FunctionDef

process方法中f_ast = ast.parse(data)解析源文件为AST抽象语法树

generic_visit(f_ast)方法中结束AST偏差并进行类型的检测

强盗工具分析

我们前面的import示例,以这里的检测任务是visit_Import

def  visit_Import ( self ,  node ):
用于 node 中的 节点名名称
如果 节点名姓名
自我import_aliases [节点名asname ] = 节点名命名
自我进口添加节点名名称
自我上下文[ “模块” ] = 节点名姓名
自我update_scores ( self.tester.run_tests ( self.context , Import ) ) _ _ _

其实就是把进口的包名,以及该节点的一些环境执行出来保存的问题self.context,然后用节点检查,如果查出就起来tester.run_testsImport

结束所有的一切都需要检测的文件中AST节点后,最后是输出结果

日志调试b_mgr.b_ma 日志_ _ 调试b_mgr.metrics _ _

# 由 Bandit Manager 触发结果输出
sev_level = constants . 排名[参数严重性 -1 ] conf_level =常量_ 排名[参数信心- 1 ] b_mgr output_results ( args.context_lines , sev_level , conf_level , args . output_file , args . output_format , args . _ _







味精模板


检测实战

当然要考虑到相关的操作情况,这里列出的列表github上开源项目代码

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

对于未经身份验证的请求,限制性限制允许您每分钟最多提出 10 个请求,考虑到本地对仓库代码进行解析和漏洞检测也需要时间,我们不进行身份验证,每分钟内完成当页内容的漏洞检测

编写一个调用Github API进行仓库下载,并使用bandit检测的脚本如下

进口 时间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 日期时间now ()
url = "https://api.github.com/search/repositories?q={}&per_page={}&page={}" 格式关键字每页
代表=请求获取网址超时= 5
项目= json 加载rep.text [ ' items ' ] for j in range len items )):rep_url = items [ j ][ 'html_url' ] cloneRsp rep_url 文件名= rep_url



split ( '/' )[ 4 ]
callBandit (文件名)
endtime = datetime 日期时间now ()
checkTime (( endtime - starttime ) . seconds )
返回def cloneRsp ( url ):
日志记录信息“克隆{}” 格式网址))
操作系统系统'git clone {}' 格式url ))def callBandit 文件名):
记录info ( "bandit {}" .format ( filename ) )
os . system ( "bandit -r ./{} -f html -o ./{}/scan_{}.html" .格式(文件名,文件名,文件名))def checkTime 运行时):
记录info ( "runtime is {}" .format ( runtime ) )
if runtime < 60 :
time . 睡眠62 - int 运行时))def main ():
getRepItem ( "cms+language:python" )如果 __name__ == '__main__' :
main ()

MAX_NUM爬取的页数,getRepItem符合要求搜索的关键词

运行之后最在clone的项目文件夹下生成scan_项目名.html的漏洞检测报告了

强盗工具分析

参考链接

  • https://ericfu.me/bandit-the-python-static-analyzer/

  • Python的脚本脆弱性检测研究与实现_刘佩

    https://blog.csdn.net/Next_Second/article/details/78238328

源:先知(https://xz.aliyun.com/t/11341#toc-1)

注:如有侵权请联系删除



强盗工具分析




强盗工具分析

欢迎大家加群一起讨论学习和交流

强盗工具分析

快乐要懂得分享,

才能加倍的快乐。


原文始发于微信公众号(衡阳信安):强盗工具分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月14日07:50:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   强盗工具分析http://cn-sec.com/archives/1114168.html

发表评论

匿名网友 填写信息