使用Git Hooks捕获API密钥,防止敏感信息泄露

本文介绍了如何利用Git Hooks中的pre-commit脚本,通过正则表达式检测代码中可能泄露的API密钥,防止敏感信息被提交到代码仓库,提升开发安全实践。

使用Git Hooks捕获API密钥

以下是我最近学到的一个小技巧,可以帮助防止API密钥等敏感信息最终进入你的Git仓库。我已经向一些热爱Git的开发者提到过这一点,他们都声称这很明显,并且已经有很多人在使用它。但是,由于我们经常在GitHub上看到密钥,我猜测这是一个人们知道应该做什么与实际在做什么之间存在差距的情况。

Git Hooks简介

Git有一个钩子系统,允许你在关键事件(如代码提交或推送到远程仓库)时运行脚本。这些脚本可用于检查文件内容或提交消息,并在必要时阻止操作。它们可以在本地和远程端运行,只需将具有正确名称的可执行文件放入正确的目录即可设置。你可以在自定义Git - Git Hooks中阅读更多相关信息。

防御机制

我建议的防御措施是在允许文件提交到仓库之前检查它们是否存在不良内容,这种检查由.git/hooks/pre-commit脚本执行。该脚本在提交时运行,但在文件实际进入仓库之前。脚本可以访问所有正在提交的文件列表,然后简单地通过grep搜索不良内容,如API密钥或任何你不想最终进入仓库的内容。脚本能够通过写入标准输出来向用户发送消息,如果脚本以零退出,则允许提交,否则拒绝提交。

示例脚本

以下脚本使用两个正则表达式来检查Amazon和Google的私钥。它对每个要提交的文件调用grep。如果grep返回内容,则表示有匹配,打印消息并增加不良文件计数。最后,脚本以不良计数值退出;如果没有匹配,则计数为零,允许提交,否则拒绝提交。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env ruby

# 此脚本可以通过在签入时使用--no-verify参数绕过

files_modified = `git diff-index --cached --name-only HEAD`
files_modified_arr = files_modified.split("\n")

# puts "Checking files: #{files_modified_arr.inspect}"

bad_files = 0

# 在这里构建所有你不想签入的密钥和内容的哈希。
# 注意斜杠引号前的双斜杠,这是为了确保在传递给grep的字符串中构建斜杠引号。

regexs = {
    "AWS Key" => "['\\\"][a-z0-9\/+]{40}['\\\"]",
    "Google Key" => "['\\\"][a-z0-9_]{39}['\\\"]",
}

files_modified_arr.each do |file|
    regexs.each_pair do |key_name, regex|
        grep_command = "grep -iE \"#{regex}\" #{file}"
        # puts grep_command
        res = `#{grep_command}`
        # puts res.inspect
        unless res == ""
            bad_files += 1
            puts "Match rule for #{key_name} on file: #{file}"
        end
    end
end

exit bad_files

第一个示例显示了API密钥的安全使用方式,它们将在使用前从文件中加载。

文件正常通过Git提交过程。

第二个示例将API密钥直接存储在文件中,可以看到,钩子检测到这一点并阻止了提交:

最后,与任何模式匹配规则一样,偶尔可能会出现误报。如果你想覆盖钩子及其检查,可以在提交时使用--no-verify参数:

结论

这种技术可用于检测任何类型的内容并防止其最终进入仓库。显然,如果正则表达式写得不好,仍然有可能漏掉一些内容;同样,写得不好的正则表达式可能导致误报,因此需要努力确保正则表达式列表尽可能严格。

此外,正如所示,检查可以轻松绕过,因此仍然建议定期进行源代码审计,寻找开发者强制通过的密钥或其他信息。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计