现在我们已经掌握了一些资源,并且对 CodeQL 和 Semgrep 有所了解,让我们深入了解它们。虽然这两种工具都是现代静态分析工具的很好的例子,但它们却大不相同。
使用案例
我首先要说的是,对于 CodeQL 和 Semgrep,我都关心一个用例,它增强了我的漏洞研究工作流程,以帮助识别给定代码库中的安全漏洞,以及 GitHub 和 R2C 主要试图向您推销的用例,利用这些工具作为左移策略的主要组成部分。他们的目标是取代您现有的 SAST,或者成为尚未推出的公司的首次实施。他们的目标是集成到 CI 管道中,以每隔一段时间或作为代码评审过程的一部分运行,并在问题投入生产之前识别问题。从他们的许可模式中可以清楚地看出这一点,我们将很快讨论。
有几类问题可用于:
- 安全漏洞
- 非安全漏洞
- 样式执行/检查
这两种工具都附带一个查询和规则库,这些查询和规则实现对这些示例的检测,并能够编写自己的查询和规则。我没有花太多时间评估每个库附带的库,以真正说明质量或全面性,因为在我的大多数使用中,我已经编写了自定义规则来检测非常具体的条件,这些条件相当适合代码库本身,而不是一般规则。
这主要用于执行变体分析,以识别存在特定漏洞模式的其他位置或执行数据流分析,同时消除采取特定步骤以消除漏洞的情况(例如,清理SQL查询的输入)。我的假设是,这些库中的通用查询和规则可能相当有限,除了最令人震惊的问题,以避免误报并应用于尽可能广泛的代码库集。包含的库是我想在未来更深入地研究的东西,但从浏览它们来看,它们本身似乎对我的用例并没有特别帮助。
发牌
许可实际上是一件大事,具体取决于您要做什么以及您需要哪些功能。CodeQL 许可相当简单。您可以完全免费使用该工具的所有功能,只要您将其与开源代码一起使用即可。第二个你想把它与封闭的源代码一起使用(除了一些狭窄的剥离),你需要一个商业许可证。这是GitHub高级安全(GHAS)中包含的内容,这是他们的商业产品之一,也是GitHub Enterprise(SaaS或服务器)的附加组件,您可以在其中按组织的每个用户付费。如果您不是现有的 GitHub 客户或尝试在 GitHub 生态系统之外使用它,祝你好运。
他们真的不想卖给你许可证,除非你准备投入一些大笔资金(数十万美元),否则他们甚至不想和你说话,即使你告诉他们你已经批准了预算并试图向他们扔钱。他们的商业模式主要集中在销售 GHAS 和向每个承诺用户收取每个正在扫描的存储库的费用,而不是为漏洞研究人员提供商业访问。作为一个领导一个进攻性安全团队的人,这个团队在短期内定期进出回购,并且没有工程师使用工具本身,这对我们来说不是一个实用或现实的选择。定价与我们的用例不一致,对于以这种方式使用它的大多数团队/企业来说是不现实的。
经过大量的来回,一些冷冰冰的电子邮件,以及骚扰合适的人,我能够获得一些非开源工作的许可证,但这是迄今为止在漏洞研究中合法使用CodeQL最痛苦的绊脚石之一。根据您的用例,这可能很重要,也可能无关紧要。除非您在内部漏洞研究团队中,或者作为咨询安全服务公司进行开放式评估,否则似乎没有很多情况可以访问您想要使用 CodeQL 的闭源码。
Semgrep 许可既简单又复杂,具体取决于您关心的功能。R2C 提供了 Semgrep 的开源版本,可用于开源和闭源软件。此 OSS 版本仅限于文件内过程内分析。他们还在销售一个新的Pro版本,其中包括具有过程间分析的文件内和具有过程间分析的迭代文件。这在“团队”层及以上层可用,同样按开发人员每月计费。他们还提供“安全顾问/早期创业公司是否有特殊定价?定价页面上的常见问题解答,这实际上是大多数研究人员将要选择Pro的道路。 不清楚此选项的许可是什么样子的,或者如果您想要Pro,获得它有多难。
到目前为止,我主要在我的用例中使用 OSS,它已经完成了我使用的狭窄范围所需要的。除了文件间和过程间支持外,OSS 和 Pro 之间的另一个主要区别是增加了一些仅限 Pro 的语言支持。在撰写本文时,唯一提到的是Apex,这是Salesforce用于定制的语言。
工具
在之前的文章中,我已经谈到了工具,特别是关于CodeQL VS Code扩展和Semgrep游乐场。我想更深入地介绍这些工具以及生态系统中存在的其他一些工具。鉴于Microsoft拥有GitHub,GitHub拥有CodeQL,很明显他们会选择VS Code来构建。我非常直言不讳地不喜欢VS Code。我认为烤面包机弹出窗口非常烦人,很多扩展都有问题,整体集成非常受欢迎。话虽如此,CodeQL 扩展非常适合使用。它确实使体验明显改善。
在代码完成、快速查询、数据库管理、集成到 GitHub、AST 可视化、查询历史记录以及与查询结果的交互之间,您真的不能要求更好的方法来使用 CodeQL。如果使用 VS Code 进行代码浏览和代码库审核,则尤其如此,它确实可以让您保持所有位置并非常集成所有内容。如果您正在迭代查询,那就太好了,因为它允许您逐步进行,尤其是当您开始重构(例如将独立查询转换为类)或开始使用更高级的功能(例如数据流或污点跟踪)时。
肯定有改进的余地,我已经给了他们一些直接的反馈。作为喜欢 JetBrains 产品的人,很高兴看到他们的生态系统中的官方扩展,但我并没有为此屏住呼吸。但这在 CodeQL 方面确实如此
GitHub本身有许多集成,并将其引入“代码扫描”,这是他们利用CodeQL的SAST产品,但一般来说,这对于漏洞研究来说可能不会特别有趣。
在Semgrep方面,故事就没有那么好了。还有一个VS Code扩展,尽管它特别指出它没有主动维护。因此,我没有亲自使用它。它是开源的,但自 2022 年以来一直没有更新。
在交互式处理结果方面,我发现的最佳选择是利用Semgrep可以生成的SARIF输出。如果您从未使用过 SARIF,它是一种使用 JSON 的开放标准文件格式,旨在成为静态分析工具之间的交换格式。VS Code 有一个扩展名,增加了对 SARIF 文件的支持。它可以加载它们并打开一个交互式窗格,该窗格允许您深入了解结果并将您带到代码中已匹配的位置。它甚至可以很好地与基于污点跟踪的发现一起使用,并专门注释发生不同污点步骤的代码。加载文件有点挑剔,但总体上效果很好。不幸的是,我还没有找到 JetBrains 生态系统的良好扩展,所以再次陷入 VS Code 中。如果这是你习惯的,你应该有宾至如归的感觉。
R2C还提供了Semgrep应用程序。它实际上是为了集成、管理调查结果和处理规则管理。总的来说,我觉得它对我的用例不是特别有用。我倾向于在本地编写规则并自己管理它们的运行/分发。如果你在一个集群中耕种,我可以看到它很有帮助,但总的来说,我的工作流程保持得很好。
语言支持
根据您使用的语言,这可能是您可以使用哪些工具的决定因素之一。这两种工具都涵盖了广泛的通用语言。您可以在此处查看 CodeQL 的支持矩阵,在此处查看 Semgrep 的支持矩阵。它们在击中许多通用语言方面都做得很好,尽管CodeQL特别不支持PHP和C,并且Semgrep中的C++支持是实验性的。需要注意的另一件事是,虽然列出了对各种语言的支持,但所有支持并不相同。
如果您浏览两者中的问题跟踪器,您会发现许多特定语言未按预期运行的问题。在我迄今为止有限的经验中,在语言支持的错误方面,我在 CodeQL 上遇到的问题比我在 Semgrep 上遇到的问题要少。我不能说客观的质量或正确性,但我可以提供一些我遇到的问题的例子。在到达那里之前,我认为简要介绍一下两者的工作原理是有意义的,因为这将提供一些背景。
我对 CodeQL 如何实现对语言的支持的理解是,他们为特定语言构建了一个提取器。这通常利用语言的编译器/解释器对代码进行建模并创建存储在数据库中的必要关系。然后需要构建一个标准库,对可用于编写查询的语言语法和语义进行建模。这个标准库是用 CodeQL 本身编写的。在大多数情况下,标准库至少会因语言而异,这意味着了解一种语言不一定会翻译成另一种语言,这可能会令人沮丧,但根据我的经验,文档非常好,从一种语言到另一种语言并不难。大多数高级概念都非常相似。
我的理解是,提取器本身是开源的,理论上你可以构建自己的,尽管作为一个做过相当多解析器开发和分析工作的人,这对于个人的大型语言来说似乎不是很实用,考虑到上面讨论的许可问题,我可能不会这样做。最终这意味着,在某些/大多数情况下,真正的解析器用于解析正在分析的代码,因此如果语言实现认为它是有效的代码,CodeQL 也应该如此。
另一方面,Semgrep利用了Tree-sitter,这是一个在许多项目中使用的通用解析器生成器库。由于Tree-sitter和Semgrep OSS是开源的,理论上也可以添加对新语言的支持,但目前还不清楚这将需要多少工作,以及它是否适用于Semgrep的Pro版本。从 GitHub 问题来看,他们似乎利用开箱即用的语法来解析语言,这是一把双刃剑。这意味着他们以最少的工作免费获得大量语言支持,但他们也仅限于现有语言,除非他们想编写自己的语言,并且受到可用语法质量的限制,除非他们想修复它们。这似乎导致能够更快地为更多语言提供支持,但这些语言并不总是最正确的。
这方面的一个例子是我在 Semgrep 的 PHP 处理中发现的一个问题,尽管 PHP 没有对函数强制区分大小写,但它将函数调用视为区分大小写。这会导致 Semgrep 中的假阴性检测。一般来说,除了偶尔的错误之外,许多非常通用的东西似乎在语言中运行良好,但是当你进入语言中一些更深奥和鲜为人知的功能时,你开始看到它们被错误地处理。
自动修复
我想指出这一点以及Semgrep提供的一些有趣的东西,这些东西可能对漏洞研究用例特别有用,也可能不是特别有用,但对于利用这些工具作为左移策略一部分的人来说可能很有趣。Semgrep 提供了在规则中定义自动修复的功能。当模式匹配时,可以将修复应用于源。从理论上讲,这可以用来自动提交拉取请求,而不需要工程师自己编写修复程序。它似乎不是非常灵活,可能不是处理披露的理想方式,如果你想这样做,但这是一种选择。
如果它是你想要利用的东西,那么它的有用性可能会非常依赖于规则(例如,你能以编程方式定义如何以正确的方式修复代码)。我不知道有多少次会有一条明确的路径,并且可能会有负面的二阶效应。
例如:
- 它是否破坏了下游软件(例如 API 损坏)?
- 它是否会更改序列化/数据格式并损坏/中断持久存储?
这些是严重的问题,我会担心依赖它,但可能是最简单的问题,直到我有一些实际经验来支持它的使用。
总结
我希望这有助于概述 CodeQL 和 Semgrep 之间的一些异同,并真正展示它们的优势和劣势所在。将来,我们将深入研究查询和规则,并对两者进行深入比较。
参考:goingbeyondgrep