一、基本介绍
Semgrep 是一个快速、开源的静态代码分析工具,其核心采用 OCaml 语言编写。主要用于在 Commit 和 CI 时查找 Bug 并强制执行代码规范。其中 Semgrep 除了提供 Semgrep CLI 还有 Semgrep CI、Semgrep App 等。但由于 Semgrep App 社区版本有 20 个人数限制,且不支持私有的 Gitlab。故下面的介绍内容全部是基于 Semgrep CLI。
首先比较重要的一点是,Semgrep 只会在本地分析代码:代码永远不会上传。
1.1 初识规则
Semgrep 的规则看起来像编写的代码;没有抽象语法树、复杂难懂的正则表达式或令人痛苦的 DSL 语言。例如下图是查找 Python print()
语句的规则。
1.2 支持语言
Semgrep 目前已经支持 20+ 语言,常见的 Go、Java、JavaScript、PHP、Python、Scala 等都已经支持。GA 代表生产级支持,已知错误很少,解析率达到 99.9%+,内置规则 10+。
1.3 安装 Semgrep
安装 Semgrep 需要 Python 3.7+
-
macOS 使用 brew 工具安装:
brew install semgrep
-
对于 Ubuntu、Windows 到 Linux 的 Windows 子系统 (WSL)、Linux、macOS:
python3 -m pip install semgrep
-
要在不安装的情况下试用 Semgrep,可以通过 Docker 运行它:
docker run --rm -v "${PWD}:/src" returntocorp/semgrep semgrep --config=auto
-
通过在终端运行 semgrep –help 来确认安装。
semgrep --help
-
运行推荐的 Semgrep Registry 规则:
semgrep --config=auto [*PATH/TO/SRC*]
二、运行规则
Semgrep 是根据相关规则来检测代码。这些规则可以发现 安全性、性能、正确性等问题并实施最佳实践。当然也可以通过 Semgrep 的规则语法定义自定义规则,也可以依赖社区或 r2c 创建的规则。规则存储在 Semgrep 注册表中。Semgrep Registry 存储在一个开源存储库中。
Semgrep 运行规则有以下几种方式:
2.1 使用 Semgrep Registry 规则
使用此规则需要本地网络能连接公网。默认情况下,当使用 Semgrep Registry 时,Semgrep 会收集使用指标。
# *PATH/TO/SRC 是带扫描的源码路径*
semgrep --config=auto [*PATH/TO/SRC*]
2.2 使用本地规则
-
临时规则
在命令行中使用 -e
or --pattern
参数来指定一次性的临时规则。
例如:检查 ==
左右两边相同的 Python(通常这是一个 bug):
semgrep -e '$X == $X' --lang=py path/to/src
-
本地文件规则
要创建一个本地 YAML 文件,在其中定义属于自己的规则。
-
创建一个 rule.yaml
文件。 -
下面是一个简单的 Python 示例规则,可以将其粘贴到 rule.yaml
文件中。
rules:
- id: is-comparison
languages:
- python
message: The operator 'is' is for reference equality, not value equality! Use
`==` instead!
pattern: $SOMEVAR is "..."
severity: ERROR
运行以下命令运行本地 YAML 规则文件:
semgrep --config path/to/rule.yaml
2.3 同时使用多个规则
要同时运行多个规则,在每个规则前使用 --config
参数。此选项可以包含本地规则以及 Semgrep Registry 规则。
semgrep --config *p/python* --config *MYRULES/MYRULE.YAML*
三、扫描结果
3.1 结果介绍
Semgrep CLI 结果是由与一段代码匹配的特定规则生成的。多个规则可以匹配同一段代码,即使它们实际上是相同的规则。例如以下规则和代码片段:
rules:
- id: finding-test
pattern: $X == $X
message: Finding test 1
languages: [python]
severity: WARNING
- id: finding-test
pattern: $X == $X
message: Finding test 2
languages: [python]
severity: WARNING
print(1 == 1)
运行 Semgrep 会产生以下结果:
test.py
severity:warning rule:finding-test: Finding test 1
1:print(1 == 1)
--------------------------------------------------------------------------------
severity:warning rule:finding-test: Finding test 2
1:print(1 == 1)
semgrep 扫描结果可以指定输出文件格式,例如可以用 -o -json 指定输出为 json 文件,支持的输出格式如下
--emacs Output results in Emacs single-line format.
--json Output results in JSON format.
--junit-xml Output results in JUnit XML format.
--sarif Output results in SARIF format.
--vim Output results in vim single-line format.
3.2 扫描时忽略指定文件
当我们有些代码不想经过 Semgrep 扫描,如何忽略文件、文件夹或部分代码呢?
方法 | 用法 | 例子 |
---|---|---|
忽略代码块:nosemgrep | 创建一个注释,后跟一个空格 ,然后nosemgrep 是匹配的第一行或前一行。 |
// nosemgrep // nosemgrep: rule-id # nosemgrep |
忽略文件和文件夹: semgrepignore | 在项目的工作目录中创建一个.semgrepignore 文件,并在其中添加文件和文件夹的模式。模式遵循带有一些警告的语法 |
.semgrepignore样本文件https://raw.githubusercontent.com/returntocorp/semgrep/develop/cli/src/semgrep/templates/.semgrepignore |
在项目的工作目录中创建一个 .semgrepignore
文件,并在其中添加文件和文件夹的模式。模式遵循带有一些警告的语法
.semgrepignore 样本文件
https://raw.githubusercontent.com/returntocorp/semgrep/develop/cli/src/semgrep/templates/.semgrepignore
如果用户没有指定 .semgrepignore
的情况下,Semgrep 将引用其存储库的默认模板:
所以 /tests,/test, /vendors文件夹默认不会被检测
Semgrep 会忽略超出使用范围的文件。
-
大文件(最大文件大小默认为 1MB) -
二进制文件 -
未知的文件扩展名(文件扩展名与任何支持的编程语言都不匹配)
例如,.jpg
文件不是 Semgrep 所支持的,所以将不会被扫描
当然也可以在 Semgrep CLI 中使用 –exclude 参数忽略特定文件或文件夹,用 --include
参数指定要扫描的文件、文件夹。
四、数据流分析
Semgrep 有一个程序内数据流分析引擎,为其提供了额外的功能。例如,常量传播、污点跟踪等。不过目前基于数据流的功能,包括污点跟踪,仍然处于测试状态,整体功能仍然较为薄弱。
4.1 常量传播
举个例子,return 42
, Semgrep 匹配 return x
,当 x 通过恒定变化减少到 42 时,将对返回的 42 与 x 匹配。
Semgrep 支持程序内常量传播。将跟踪变量是否必须在程序中的给定点携带一个常数值。Semgrep 然后在匹配模式时执行常量合并。目前它可以跟踪布尔、数字和字符串常量。
使用常量传播,metavariable-comparison
运算符将可以代替任何常量变量,而不仅仅是固定的字符串。
4.2 污点跟踪
Semgrep 支持程序内污点跟踪。这是一种数据流分析,可跟踪整个程序中不受信任(也称为“污染”)数据的流动。
污点跟踪规则必须指定 mode: taint
,这将启用以下运算符:
-
pattern-sources
(必需的) -
pattern-sinks
(必需的) -
pattern-sanitizers
(可选的)
污点分析可以抽象成一个三元组 <sources,sinks,sanitizers> 的形式。
source 即污点源,代表直接引入不受信任的数据或者机密数据到系统中;
sink 即污点汇聚点,代表直接产生安全敏感操作(违反数据完整性)或者泄露隐私数据到外界(违反数据保密性);
sanitizer 即无害处理,代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害。
简单的说:污点分析是默认不信任本地/外部输入,将本地及外部输入的控制/数据流过程进行分析,如果没有经过无害化处理,即认为存在漏洞的漏洞模型
污点分析功能更多功能更可参考如下链接:https://semgrep.dev/docs/writing-rules/data-flow/taint-mode/
五、延伸
这里介绍了 semgrep 的一些使用和原理,但是最重要的一个没有介绍,如何编写属于自己的 Semgrep 规则?毕竟 Semgrep 官方自带的规则,可能并不满足我们的需求,而且个别官方的规则有些 Bug。
例如笔者前段时间使用的默认 Python 规则”unquoted-csv-writer”,其中的修复建议是有问题的,按照这个修复建议,仍然会有 CSV 注入风险,详情参考:https://github.com/returntocorp/semgrep-rules/issues/2351下一章节将会介绍,Semgrep 规则,敬请期待。
原文始发于微信公众号(洋洋自语):Semgrep 之初识(一)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/272948.html