Python 程序源码静态分析工具调研

Python 程序分析工具调研

1.Bandit:构建 AST 并使用插件检查安全问题,最初在 OpenStack 安全项目中开发,后来被重新定位到 PyCQA。主要用于扫描危险函数,支持自定义漏洞测试和扩展插件。

识别问题信息:

[main]	INFO	profile include tests: None
[main]	INFO	profile exclude tests: None
[main]	INFO	cli include tests: None
[main]	INFO	cli exclude tests: None
[main]	INFO	running on Python 3.11.3
Run started:2023-08-03 03:09:58.766531

Test results:
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/learn/http/http_request.py:14:11
13	
14	response = requests.get('https://www.imooc.com')
15	content = str(response.content, encoding='utf-8') # ==> 打印具体内容

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: '123456'
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b105_hardcoded_password_string.html
   Location: ./HelloPython/src/com/python/learn/learn1_for_if.py:18:11
17	account = 'qiyue'
18	password = '123456'
19	

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/__init__.py:25:13
24	    upload_url = uri + "/put/ts/js/data/" + tenantId
25	    result = request.post(upload_url, headers={"Content-Type": "application/json"}, json=data)
26	    print(result.text)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/__init__.py:31:11
30	def get_num(start_num, end_num):
31	    return random.randrange(start_num, end_num) + random.randrange(0, 9) * 0.1
32	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/__init__.py:31:50
30	def get_num(start_num, end_num):
31	    return random.randrange(start_num, end_num) + random.randrange(0, 9) * 0.1
32	

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/__init__.py:38:13
37	    paths = [browsePath]
38	    result = request.post(query_url, headers={"Content-Type": "application/json"}, json=paths)
39	    print(result.text)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/__init__.py:55:38
54	    ljdl_old_value = get_path_value(eq_uri + "/zljblz/ljydl")[0].get("v").__int__()
55	    ljdl_end_value = ljdl_old_value + random.randrange(1, 9) * 10
56	    ljydl = get_num(ljdl_old_value, ljdl_end_value)  # 累计电量

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/data_demo.py:25:13
24	    upload_url = uri + "/put/ts/js/data/" + tenantId
25	    result = request.post(upload_url, headers={"Content-Type": "application/json"}, json=data)
26	    print(result.text)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/data_demo.py:31:11
30	def get_num(start_num, end_num):
31	    return random.randrange(start_num, end_num) + round(random.randrange(0, 9) * 0.1,1)
32	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/data_demo.py:31:56
30	def get_num(start_num, end_num):
31	    return random.randrange(start_num, end_num) + round(random.randrange(0, 9) * 0.1,1)
32	

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/data_demo.py:38:13
37	    paths = [browsePath]
38	    result = request.post(query_url, headers={"Content-Type": "application/json"}, json=paths)
39	    print(result.text)

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/write_data.py:24:13
23	    upload_url = uri + "/put/ts/js/data/" + tenantId
24	    result = request.post(upload_url, headers={"Content-Type": "application/json"}, json=data)
25	    print(result.text)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/write_data.py:30:11
29	def get_num(start_num, end_num):
30	    return random.randrange(start_num, end_num) + round(random.randrange(0, 9) * 0.1,1)
31	

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/write_data.py:30:56
29	def get_num(start_num, end_num):
30	    return random.randrange(start_num, end_num) + round(random.randrange(0, 9) * 0.1,1)
31	

--------------------------------------------------
>> Issue: [B113:request_without_timeout] Requests call without timeout
   Severity: Medium   Confidence: Low
   CWE: CWE-400 (https://cwe.mitre.org/data/definitions/400.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/plugins/b113_request_without_timeout.html
   Location: ./HelloPython/src/com/python/model/write_data.py:37:13
36	    paths = [browsePath]
37	    result = request.post(query_url, headers={"Content-Type": "application/json"}, json=paths)
38	    print(result.text)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: ./HelloPython/src/com/python/model/write_data.py:126:43
125	            params = [dataInfo(id=eq_uri + "/zljblz/eer", s=0, t=now,
126	                               v=5 + round(random.randrange(3, 7) * 0.1,1), vtype="F")
127	                      ]

--------------------------------------------------

Code scanned:
	Total lines of code: 392
	Total lines skipped (#nosec): 0

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 9
		Medium: 7
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 7
		Medium: 1
		High: 8
Files skipped (0):

2.Vulture:同样利用了 ast 模块生成抽象语法树,在遍历时记录已定义和使用的对象名称,最后报告未使用的对象(死代码)。还通过查找 return、break、continue、raise、不满足条件的 if 条件、while 条件来检测不可达的代码。因为只考虑对象名称,没有考虑作用域,因此可能存在漏报,而且隐式调用可能会被误报。

可信度为函数执行的可信度

image-20230807101146882

检测报告:

/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/__init__.py:8: unused variable 'edzll_1' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/__init__.py:9: unused variable 'edzll_2' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/__init__.py:10: unused variable 'edzll_3' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/__init__.py:13: unused variable 'nhb' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/data_demo.py:8: unused variable 'edzll_1' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/data_demo.py:9: unused variable 'edzll_2' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/data_demo.py:10: unused variable 'edzll_3' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py:7: unused variable 'edzll_1' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py:8: unused variable 'edzll_2' (60% confidence, 1 line)
/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py:9: unused variable 'edzll_3' (60% confidence, 1 line)

3.Pysa:由 Facebook 开源的 Pyre 是兼容 PEP 484 的 Python 性能类型检查器,可以增量分析大型代码库,能够迅速处理百万级别的代码。Pyre 附带了 Pysa,一个关注安全性的静态分析工具,Pysa 是 Python Static Analyzer 的缩写,Pysa 支持追踪和分析 Python 程序中的数据流(污点分析)。

会递归检索,但程序及依赖需要配置到环境中

并在目录下配置相关的检索配置文件:.pyre_configuration

检测信息报告:

ƛ No cached overrides loaded, computing overrides...
ƛ `google.protobuf.message.Message.ClearField` has 57 overrides, this might slow down the analysis considerably.
ƛ `google.protobuf.message.Message.__init__` has 58 overrides, this might slow down the analysis considerably.
ƛ `object.__eq__` has 82 overrides, this might slow down the analysis considerably.
ƛ `object.__init__` has 754 overrides, this might slow down the analysis considerably.
ƛ `object.__ne__` has 60 overrides, this might slow down the analysis considerably.
ƛ `type.__call__` has 131 overrides, this might slow down the analysis considerably.
ƛ `type.__init__` has 448 overrides, this might slow down the analysis considerably.
ƛ `type.__new__` has 75 overrides, this might slow down the analysis considerably.
[
  {
    "line": 12,
    "column": 18,
    "stop_line": 12,
    "stop_column": 35,
    "path": "views.py",
    "code": 5001,
    "name": "Possible RCE:",
    "description":
      "Possible RCE: [5001]: User specified data may reach a code execution sink",
    "long_description":
      "Possible RCE: [5001]: User specified data may reach a code execution sink",
    "concise_description":
      "Possible RCE: [5001]: User specified data may reach a code execution sink",
    "inference": null,
    "define": "views.operate_on_twos"
  }
]

4*.PyCG :PyCG 使用静态分析生成 Python 代码的调用图。它有效地支持

  • 高阶函数
  • 扭曲的类继承方案
  • 自动发现导入的模块以进行进一步分析
  • 嵌套定义

输出信息为类之间的依赖和嵌套关系:

{
    "...src.com.python.model": [
        "datetime.datetime.now",
        "<builtin>.print",
        "...src.com.python.model.set_eq_data",
        "...src.com.python.model.get_eq_data_info",
        "time.sleep"
    ],
    "...src.com.python.model.dataInfo": [],
    "...src.com.python.model.uplod_ts_data": [
        "<builtin>.print",
        "requests.post"
    ],
    "requests.post": [],
    ".print": [],
    "...src.com.python.model.get_num": [
        "random.randrange"
    ],
    "random.randrange": [],
    "...src.com.python.model.get_path_value": [
        "<builtin>.print",
        "requests.post",
        "requests.post.json.get",
        "requests.post.json"
    ],
    "requests.post.json": [],
    "requests.post.json.get": [],
    "...src.com.python.model.get_eq_data_info": [
        "...src.com.python.model.get_path_value",
        "<builtin>.round",
        "<builtin>.print",
        "random.randrange",
        "...src.com.python.model.get_num"
    ],
    ".round": [],
    "...src.com.python.model.set_eq_data": [
        "<builtin>.print",
        "...src.com.python.model.uplod_ts_data",
        "...src.com.python.model.dataInfo",
        "time.time"
    ],
    "time.time": [],
    "datetime.datetime.now": [],
    "time.sleep": [],
    "...src.com.python.model.data_demo": [
        "datetime.datetime.now",
        "<builtin>.print",
        "...src.com.python.model.data_demo.get_eq_data_info",
        "time.sleep",
        "...src.com.python.model.data_demo.set_eq_data"
    ],
    "...src.com.python.model.data_demo.dataInfo": [],
    "...src.com.python.model.data_demo.uplod_ts_data": [
        "<builtin>.print",
        "requests.post"
    ],
    "...src.com.python.model.data_demo.get_num": [
        "<builtin>.round",
        "random.randrange"
    ],
    "...src.com.python.model.data_demo.get_path_value": [
        "<builtin>.print",
        "requests.post",
        "requests.post.json.get",
        "requests.post.json"
    ],
    "...src.com.python.model.data_demo.get_eq_data_info": [
        "<builtin>.round",
        "<builtin>.print",
        "...src.com.python.model.data_demo.get_path_value",
        "...src.com.python.model.data_demo.get_num"
    ],
    "...src.com.python.model.data_demo.set_eq_data": [
        "time.time",
        "...src.com.python.model.data_demo.uplod_ts_data",
        "<builtin>.print",
        "...src.com.python.model.data_demo.get_num",
        "...src.com.python.model.data_demo.dataInfo"
    ],
    "...src.com.python.model.write_data": [
        "<builtin>.round",
        "<builtin>.print",
        "...src.com.python.model.write_data.dataInfo",
        "random.randrange",
        "...src.com.python.model.write_data.uplod_ts_data"
    ],
    "...src.com.python.model.write_data.dataInfo": [],
    "...src.com.python.model.write_data.uplod_ts_data": [
        "<builtin>.print",
        "requests.post"
    ],
    "...src.com.python.model.write_data.get_num": [
        "<builtin>.round",
        "random.randrange"
    ],
    "...src.com.python.model.write_data.get_path_value": [
        "<builtin>.print",
        "requests.post",
        "requests.post.json.get",
        "requests.post.json"
    ],
    "...src.com.python.model.write_data.get_eq_data_info": [
        "<builtin>.round",
        "<builtin>.print",
        "...src.com.python.model.write_data.get_path_value",
        "...src.com.python.model.write_data.get_num"
    ],
    "...src.com.python.model.write_data.set_eq_data": [
        "time.time",
        "<builtin>.print",
        "...src.com.python.model.write_data.dataInfo",
        "...src.com.python.model.write_data.get_num",
        "...src.com.python.model.write_data.uplod_ts_data"
    ]
}

静态代码分析工具:

img

5.pytype

Pytype 检查并推断 Python 代码的类型 - 无需类型注释。Pytype 可以:

  • Lint 纯 Python 代码,标记常见错误,例如拼写错误的属性名称、不正确的函数调用等等甚至跨文件边界。
  • 强制执行用户提供的类型注释。虽然注释对于 pytype 来说是可选的,但它会检查并应用它们。
  • 在独立文件(“ pyi 文件”)中生成类型注释,可以使用提供的merge-pyi工具将其合并回 Python 源 。

Pytype是一个静态分析器;它不执行它所运行的代码。

Google 的数千个项目都依赖 pytype 来保持其 Python 代码类型正确且无错误。

Computing dependencies
Analyzing 1 sources with 0 local dependencies
ninja: Entering directory `.pytype'
[1/1] check com.python.model.write_data
FAILED: /Users/dingzhenying/project/pythonProject/HelloPython/.pytype/pyi/com/python/model/write_data.pyi 
/Users/dingzhenying/project/pythonProject/HelloPython/myenv/bin/python3.8 -m pytype.single --imports_info /Users/dingzhenying/project/pythonProject/HelloPython/.pytype/imports/com.python.model.write_data.imports --module-name com.python.model.write_data --platform darwin -V 3.8 -o /Users/dingzhenying/project/pythonProject/HelloPython/.pytype/pyi/com/python/model/write_data.pyi --analyze-annotated --enable-cached-property --nofail --quick /Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py
File "/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py", line 22, in <module>: Invalid type annotation '<instance of Callable>' for data [invalid-annotation]
  Not a type
File "/Users/dingzhenying/project/pythonProject/HelloPython/src/com/python/model/write_data.py", line 30, in get_num: Function random.randrange was called with the wrong arguments [wrong-arg-types]
         Expected: (start: int, ...)
  Actually passed: (start: float, ...)
Called from (traceback):
  line 54, in get_eq_data_info

For more details, see https://google.github.io/pytype/errors.html
ninja: build stopped: subcommand failed.
Leaving directory '.pytype'

6、mypy

最早的官方推出的mypy是由Python之父Guido van Rossum亲自开发,被各种主流编辑器所集成(如PyCharm, Emacs, Sublime Text, VS Code等),用户基础和文档经验都很丰富。

(myenv) iMonster-PC:HelloPython dingzhenying$ mypy src/com/python/model/write_data.py 
src/com/python/model/__init__.py:5: error: Library stubs not installed for "requests"  [import]
src/com/python/model/__init__.py:23: error: Function "com.python.model.dataInfo" is not valid as a type  [valid-type]
src/com/python/model/__init__.py:23: note: Perhaps you need "Callable[...]" or a callback protocol?
src/com/python/model/write_data.py:4: error: Library stubs not installed for "requests"  [import]
src/com/python/model/write_data.py:4: note: Hint: "python3 -m pip install types-requests"
src/com/python/model/write_data.py:4: note: (or run "mypy --install-types" to install all missing stub packages)
src/com/python/model/write_data.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
src/com/python/model/write_data.py:22: error: Function "com.python.model.write_data.DataInfo" is not valid as a type  [valid-type]
src/com/python/model/write_data.py:22: note: Perhaps you need "Callable[...]" or a callback protocol?
Found 4 errors in 2 files (checked 1 source file)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值