
Выявляйте жестко закодированные секреты в статическом структурированном тексте

«Мои птички повсюду, даже на Севере, они шепчут мне самые странные истории.» — Лорд Варис
Whispers — это инструмент статического анализа кода, предназначенный для разбора различных распространённых форматов данных в поисках жёстко заданных учётных данных и опасных функций. Whispers можно запускать в CLI или интегрировать в конвейер CI/CD.
Whispers задуман как парсер структурированного текста, а не код.
Сейчас поддерживаются следующие часто используемые форматы:
Файлы Python3 разбираются как AST благодаря встроенной поддержке языка.
Следующие языковые файлы разбираются как текст и проверяются на стандартные шаблоны объявления переменных и присваивания:
pip3 install whispers
git clone https://github.com/Skyscanner/whispers
cd whispers
make install
whispers --help
whispers --info
whispers source/code/fileOrDir
whispers --config config.yml source/code/fileOrDir
whispers --output /tmp/secrets.yml source/code/fileOrDir
whispers --rules aws-id,aws-secret source/code/fileOrDir
whispers --severity BLOCKER,CRITICAL source/code/fileOrDir
whispers --exitcode 7 source/code/fileOrDir
from whispers.cli import parse_args
from whispers.core import run
src = "tests/fixtures"
configfile = "whispers/config.yml"
args = parse_args(["-c", configfile, src])
for secret in run(args):
print(secret)
В Whispers доступно несколько опций конфигурации. Можно включать/исключать результаты на основе пути к файлу, ключа или значения. Спецификации путей к файлам интерпретируются как glob. Ключи и значения принимают регулярные выражения и несколько других параметров. Встроен файл конфигурации по умолчанию, который будет использоваться, если не предоставить пользовательский.
config.yml должна иметь следующую структуру:
include:
files:
- "**/*.yml"
exclude:
files:
- "**/test/**/*"
- "**/tests/**/*"
keys:
- ^foo
values:
- bar$
rules:
starks:
message: Whispers from the North
severity: CRITICAL
value:
regex: (Aria|Ned) Stark
ignorecase: True
Самый быстрый способ настроить обнаружение (например, убрать ложные срабатывания и нежелательные результаты) — скопировать стандартный config.yml в новый файл, адаптировать его и передать в качестве аргумента Whispers.
whispers --config config.yml --rules starks src/file/or/dir
Правила определяют, что именно следует извлекать из пар «ключ-значение». Есть несколько встроенных правил, таких как AWS-ключи и пароли, но инструмент легко расширяется новыми правилами.
rules:rule-id: # уникальное имя правила
description: Значения, форматированные как AWS Session Token
message: AWS Session Token # в отчёте будет показано это сообщение
severity: BLOCKER # одно из BLOCKER, CRITICAL, MAJOR, MINOR, INFO
key: # задание формата ключа
regex: (aws.?session.?token)?
ignorecase: True # регистронезависимое сравнение
value: # задание формата значения
regex: ^(?=.*[a-z])(?=.*[A-Z])[A-Za-z0-9\+\/]{270,450}$
ignorecase: False # регистрозависимое сравнение
minlen: 270 # значение должно быть длиной не менее этого
isBase64: True # значение закодировано в base64
isAscii: False # значение при декодировании является бинарными данными
isUri: False # значение не отформатировано как URI
similar: 0.35 # максимально допустимое сходство между ключом и значением
# (1.0 означает полное совпадение)
Вся функциональность разбора реализована через плагины. Каждый плагин реализует класс с методом pairs(), который проходит по файлам и возвращает пары «ключ-значение» для проверки правилами.
class PluginName:
def pairs(self, file):
yield "key", "value"