ynori7/credential-detector
GitHub: ynori7/credential-detector
一款高度可配置的源代码与配置文件硬编码凭据扫描工具,通过结合模式匹配与变量命名上下文分析,帮助团队在代码库中高效发现潜在的密钥泄露风险。
Stars: 21 | Forks: 3
# Credential-Detector [](https://goreportcard.com/report/github.com/ynori7/credential-detector) [](https://travis-ci.com/github/ynori7/credential-detector)
这个简单的命令允许您扫描项目以检测潜在的硬编码凭证。
硬编码凭证是指密码、API 密钥、授权令牌或私钥等身份验证数据,它们被直接嵌入到源代码或静态配置文件中,
而不是从外部源获取或在部署/运行时注入。这种常见做法极大地增加了恶意用户猜测密码并获取您系统访问权限的可能性。
使用此工具,您可以轻松找到被错误(或天真地)提交到您存储库中的凭证,以便将其撤销并替换为更安全的做法。
延伸阅读:
- [CWE-798:硬编码凭证的使用](https://cwe.mitre.org/data/definitions/798.html)
- [OWASP 硬编码密码的使用](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password)
## 安装
```
go install github.com/ynori7/credential-detector
```
## 使用
`go run main.go --config config.yaml --path "/home/me/myproject"`
输出示例:
```
In /home/me/myproject
Line 711:
secret = "Dklj34k3oi23kD"
```
如果省略 config 标志,将使用默认配置。
为了方便起见,还提供了一个名为 [detect-credentials-in-github-org.sh](scripts/detect-credentials-in-github-org.sh) 的脚本,
可用于获取您 Github 组织中的所有存储库以对其进行扫描。
## 功能
这款高度可配置的工具会扫描多种文件类型以搜索潜在的凭证。它会报告名称可疑的变量(排除那些值明显为测试数据或某些常量(例如标头名称)的变量)。
此外,它还会搜索代码注释和各种配置文件。扫描器还可以检测私钥和证书文件。
Credential-detector 可以扫描:
- Go 代码
- JSON 文件
- YAML 文件
- 属性文件
- 私钥/证书文件
- XML 文件
- PHP 代码
- 通用文本文件
- Bash 文件
- 通用代码(Java/C/C++ 风格)
- Javascript/HTML 文件
## Web 应用
这里有一个 Web 应用,它包含了此工具中可用的各种功能,并以便捷的方式呈现出来。使用以下命令在本地运行该应用:
```
go run cmd/web/main.go
```
请注意,获取远程存储库依赖于 `gh` 命令。UI 界面如下所示:

## 作为库使用
凭证扫描器也可以像这样作为库使用:
```
package main
import (
"log"
"github.com/ynori7/credential-detector/config"
"github.com/ynori7/credential-detector/parser"
)
func main() {
//Specify the configuration file paths. Use empty string as root config to use default root
conf, err := config.LoadConfig("myconfig.yaml", "myrootconfig.yaml")
if err != nil {
log.Fatal(err.Error())
}
p := parser.NewParser(conf)
if err := p.Scan("/myScanPath"); err != nil {
log.Fatal(err.Error())
}
//results are in p.Results
}
```
## 配置
运行凭证检测器时,可以提供一个可选的 `--root_config` 来提供基础配置,以及一个 `--config` 来定义对基础配置的任何添加/修改。
以下配置选项可用(这些值是简化的示例。完整默认值请参见 config/default_config.yaml):
```
variableNamePatterns:
- (?i)passwd|password
- (?i)secret
- (?i)token
- (?i)apiKey|api[_-]key
variableNameExclusionPattern: (?i)format|tokenizer|secretName
xmlAttributeNameExclusionPattern: (?i)token #values that tend to have a different meaning for xml
valueMatchPatterns:
- name: Postgres URI
pattern: postgres:\/\/.+:.+@.+:.+\/.+
- name: JWT Token
pattern: eyJhbGciOiJIUzI1NiIsInR5cCI[a-zA-Z0-9_.]+
variableValueExcludePatterns:
- (?i)^test$|password|^postgres$|^root$|^foobar$|^example$|^changeme$|^default$|^master$ #common dummy values
fullTextValueExcludePatterns:
- postgres:\/\/.+:.+@localhost:.+\/.+ #default postgres uri for testing
- postgres:\/\/.+:.+@127.0.0.1:.+\/.+ #default postgres uri for testing
- postgres:\/\/postgres:postgres@postgres:.+\/.+ #default postgres uri for testing
minPasswordLength: 6 #don't consider anything shorter than this as a possible credential
excludeTests: true
testDirectories:
- test
ignoreFiles: #files or directories to skip
- vendor
excludeComments: false
scanTypes: #possible values are go|yaml|json|properties|privatekey|xml|php|javascript|html|generic|generic_code
- go
- yaml
- json
- properties
- privatekey
- xml
- php
- bash
- generic
- generic_code
- javascript
- html
genericFileExtensions:
- txt
- md
- html
genericCodeFileExtensions:
- java
- swift
- cpp
disableOutputColors: false
verbose: false
```
请注意,上述值为默认值。
|配置选项|描述|值|
|-------------|-----------|------|
|variableNamePatterns|用于匹配潜在可疑变量名的正则表达式|正则表达式列表|
|variableNameExclusionPattern|用于排除不感兴趣的变量名(例如 passwordFormat 模式)的正则表达式|一个正则表达式|
|xmlAttributeNameExclusionPattern|用于排除 XML 属性的正则表达式,因为 XML 通常描述模型而不是包含数据。|一个正则表达式|
|valueMatchPatterns|用于匹配潜在可疑值的模式列表,与变量名无关|包含名称和正则表达式的对象列表|
|variableValueExcludePatterns|用于排除值(例如测试数据或定义标头名称等的常量)的模式列表。仅当我们查看变量赋值时才应用这些模式。|正则表达式列表|
|fullTextValueExcludePatterns|用于排除值(例如测试数据或定义标头名称等的常量)的模式列表。这些模式应用于变量赋值和常规的全文本扫描。|正则表达式列表|
|excludeTests|用于排除扫描测试文件的布尔标志|true 或 false|
|testDirectories|被视为仅包含测试数据的目录名称列表|字符串列表|
|ignoreFiles|应被忽略的目录或文件名列表|字符串列表|
|excludeComments|用于排除扫描代码中注释的布尔标志|true 或 false|
|scanTypes|应被扫描的文件类型列表|包含以下值的字符串列表:go, json, yaml, properties, privatekey, xml, php, bash, javascript, html, generic 或 generic_code|
|genericFileExtensions|可作为纯文本解析的文件扩展名列表。将扫描这些文件以进行可能的值匹配|
|genericCodeFileExtensions|可作为通用代码解析的文件扩展名列表。|
|disableOutputColors|用于在打印结果时禁用彩色输出的布尔标志|true 或 false|
|verbose|用于切换在解析特定文件时发生的警告消息输出的布尔标志|true 或 false|
config/default_config.yaml 中的配置是默认的根配置。如果提供了 `--config` 标志,
布尔字段和 scanTypes 的值将从此配置中获取,并且如果非空,将获取 minPasswordLength 和 variableNameExclusionPattern 的值。
对于所有其他列表属性,所提供配置中的值将被附加到根配置中。
## 与 Gosec 的比较
Credential-detector 更加灵活,因为它可以轻松配置比 gosec 更多的选项,而且它的速度明显更快,尤其是在扫描大型目录时。
以下是使用 testdata 目录中的 dummy.go 文件进行的比较:
gosec:
```
$ time gosec -include=G101 testdata
[gosec] 2021/08/07 21:14:01 Including rules: G101
[gosec] 2021/08/07 21:14:01 Excluding rules: default
[gosec] 2021/08/07 21:14:01 Import directory: /home/sfinlay/go/src/github.com/ynori7/credential-detector/testdata
[gosec] 2021/08/07 21:14:01 Checking package: testdata
[gosec] 2021/08/07 21:14:01 Checking file: /home/sfinlay/go/src/github.com/ynori7/credential-detector/testdata/dummy.go
Results:
[/home/sfinlay/go/src/github.com/ynori7/credential-detector/testdata/dummy.go:43] - G101 (CWE-798): Potential hardcoded credentials (Confidence: LOW, Severity: HIGH)
42:
> 43: var PasswordFormat = "([0-9]+):(.+)"
44:
[/home/sfinlay/go/src/github.com/ynori7/credential-detector/testdata/dummy.go:9] - G101 (CWE-798): Potential hardcoded credentials (Confidence: LOW, Severity: HIGH)
8: anotherOkayOne = "blah"
> 9: authToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
10: )
Summary:
Gosec : dev
Files : 1
Lines : 53
Nosec : 0
Issues : 2
real 0m0,116s
user 0m0,112s
sys 0m0,035s
```
credential-detector:
```
In testdata/dummy.go
Line 5:
internalSecret = "asdfasdfasdf"
Line 9:
authToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
Line 13:
AccessCode = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
Line 17:
RealPostgresUri = "postgres://myuser:pas2sword123@blah.com:5432/mydb?sslmode=disable"
Line 20:
Possible Postgres URI
/*
Multiline comment
postgres://myuser:pas2sword123@somepostgresdb:5432/mydb?sslmode=disable
*/
Line 47:
blahToken = "pas2sword123"
Line 51:
Possible JWT Token
// this is a local comment
// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
Line 54:
Possible AWS Client ID
NewStaticCredentials("AKIAYTHMXXXGSVYYYWE6", "rP22kgSajDwOyWVU/iiii1UEdJk333QUbxwtiVCe")
real 0m0,008s
user 0m0,000s
sys 0m0,010s
```
credential-detector 快了 16 倍,发现了 gosec 在 Go 代码中遗漏的七个值,并在 gosec 未检查的其他文件中额外发现了 24 个结果,
同时排除了 gosec 报告的一个误报。
## 与 Github Advanced Security 和 Spectral 的比较
像 GHAS 和 Spectral 这样的工具仅以模式识别为导向。这意味着它们会搜索具有可识别模式的知名凭证类型,例如 AWS 客户端 ID 或 Google API 密钥。
这种方法的局限性在于它只能检测知名的凭证,而不能检测自定义凭证,如内部 API 密钥或用户密码等。
这个项目的不同之处在于它除了通过模式检测凭证外,还通过上下文进行检测。它不仅关注值的外观(是否匹配某种模式),还关注其似乎被使用的方式(例如,基于赋值给它的变量名)。
这使得 credential-detector 更加健壮,因为它可以检测各种凭证和机密信息,而不仅仅是知名类型。
与 credential-detector 检测到的 32 个结果相比,GHAS 以及类似 GitGuardian 这样的工具仅在此存储库的测试文件中检测到了两个凭证(虚拟 SendGrid API Key 和虚拟 AWS Client ID)。
## 局限性
Go 扫描器仅扫描全局变量和常量。它不会检测到类似这样的情况:
```
type Config {
Secret string
}
var conf = Config{
Secret: "blah", //struct fields are not checked
}
func main() {
password := "blah" //local variables are not scanned
}
```
XML 往往会产生大量误报,因为它通常只描述模型而不实际包含数据,如下所示:
```
....
```
标签:API密钥泄露, CWE-798, DevSecOps, EVTX分析, GitHub组织安全, Go语言, TLS, 上游代理, 云安全监控, 凭据检测, 前端框架, 安全助手, 密码检查, 对抗攻击, 微调策略, 提示注入防御, 敏感信息检测, 日志审计, 源代码安全, 硬编码密码扫描, 程序破解, 配置文件扫描, 防御工具, 静态分析