代码审计工具 Cobra 源码分析(二)

代码审计工具 Cobra 源码分析(二)

0x00 前言

几天前发过一篇笔记:代码审计工具 Cobra 源码分析(一),通过pdb动态调试对代码审计工具 Cobra 的执行流程做了一个简要的分析。

在之后的文章中将记录下我对该工具部分代码的分析,可能是一个文件、也可能是一个类或者方法,看到哪里写到哪里吧,纯粹是为了记录。

0x01 分析工具及环境

Pycharm 2017.3.2(Professional Edition)

Notepad++ v7.5.2

Python 2.7.12

0x02 漏扫函数 scan_parser() 分析

scan_parser()是漏洞扫描函数,其主要的功能是对文件中的相应代码做安全审计,原理主要有两点:

1、判断代码中是否存在敏感函数

2、通过回溯传入敏感函数的参数,参数可控,则漏洞存在,反之漏洞不存在

scan_parser() 定义位置:\cobra\parser.py 第667-689行

def scan_parser(code_content, sensitive_func, vul_lineno, repair):
    """
    开始检测函数
    :param code_content: 要检测的文件内容
    :param sensitive_func: 要检测的敏感函数,传入的为函数列表
    :param vul_lineno: 漏洞函数所在行号
    :param repair: 对应漏洞的修复函数列表
    :return:
    """
    try:
        global repairs
        global scan_results
        repairs = repair
        scan_results = []
        parser = make_parser()
        all_nodes = parser.parse(code_content, debug=False, lexer=lexer.clone(), tracking=with_line)
        for func in sensitive_func:  # 循环判断代码中是否存在敏感函数,若存在,递归判断参数是否可控;对文件内容循环判断多次
            back_node = []
            analysis(all_nodes, func, back_node, int(vul_lineno), function_params=None)
    except SyntaxError as e:
        logger.warning('[AST] [ERROR]:{e}'.format(e=e))

    return scan_results

scan_parser() 漏洞扫描函数回溯调用链:

0、\cobra\parser.py 第667-689行定义scan_parser()函数

1、\cobra\engine.py 第634行 Core类中scan()方法调用scan_parser()函数

2、\cobra\engine.py 第345行 SingleRule类中process()方法调用Core类中scan()方法

3、\cobra\engine.py 第144行 scan_single()函数调用SingleRule类中process()方法

4、\cobra\engine.py 第194行 scan()函数已多进程的方式对scan_single()函数进行调用,并将相应的漏扫结果存储于回调函数store()中(第163-169行定义,其为scan()函数的内置函数)

5、\cobra\cli.py 第91行 start()函数调用scan()函数

6、\cobra\__init__.py 第82行 main()函数调用start()函数

7、\cobra.py 第22行 调用main()函数【此处即为程序入口】

好,既然已经理清楚了函数调用链,现在就可以重点分析scan_parser()函数了。

scan_parser()函数一共有4个参数,结合注释以及我的实际测试,各个参数的内容为:

def scan_parser(code_content, sensitive_func, vul_lineno, repair):

1、code_content 参数:即需要进行漏洞扫描的文件内容,通常为程序启动后遍历目标项目中的每一个文件(在分析时将仅传入一个文件便于理解),参数类型为【字符串类型】

2、sensitive_func 参数:即可能引起漏洞的敏感函数列表,参数类型为【列表类型】

3、vul_lineno 参数:即存在漏洞代码的对应行号,其实叫代码行号会更贴切一些,因为并不是每一行都存在漏洞,参数类型为【unicode字符串】

4、repair 参数:即判断存在漏洞后,给出相应的漏洞修复函数,参数类型为【列表类型】

第681-682行是是该程序的精髓所在,通过【make_parser() 语法分析】、【lexer.clone() 词法分析】对文件中的代码做处理(此处要打个标签,有机会系统的学习下编译原理的知识)。

第685行 调用analysis()函数,跟进,其在610-664行定义。而后该函数又调用了anlysis_function()、analysis_eval()、analysis_echo_print()、analysis_file_inclusion()、analysis_if_else(),对文件内容一行一行处理(在判断语句、循环语句、赋值语句、函数调用、文件包含语句中执行不同的分析函数)。

这里拿其中一个函数的实现方式举例:anlysis_function()函数,在其在340-367行定义。

第352行,判断当前代码是否为敏感函数,若是敏感函数则继续向下跟进,根据参数的不同类型做进一步分析

拿php.Variable节点来说,会进入到该函数,对其是否可可控做进一步分析。

last处理完毕后,将其结果存储在\cobra\engine.py 第634行 Core类中的scan方法内的result变量中。

再继续后续的分析和处理,不是本小结的重点,由于时间关系,有点累了,回家睡觉。之后再继续分析记录。

0x03 后记

Cobra中好多函数、类中的方法同名,不同文件中还有不通功能的同名方法,翻起来实在是有点累~

当然,由于本人对《编译原理》相关的知识掌握的并不牢靠,笔记中有错误再说难免,权当提供一个思路吧。如有谬误,还请不吝赐教。

0x04 传送门

wufeifei/cobra

代码审计工具 Cobra 源码分析(一)

发布于 2018-01-08 22:40