
Декларативный фреймворк оркестрации тестирования на проникновение
Decker — это фреймворк для оркестрации тестирования на проникновение. Он использует HashiCorp Configuration Language 2 (тот же язык конфигурации, что и Terraform) для декларативного описания тестирования на проникновение как кода, что позволяет версионировать ваши тесты, делиться ими, повторно использовать и совместно работать с командой или сообществом.
Пример конфигурационного файла decker:
// переменные берутся из окружения
// пример: DECKER_TARGET_HOST
// они будут доступны во всех конфигурационных файлах как var.*
// пример: ${var.target_host}
variable "target_host" {
type = "string"
}
// ресурсы ссылаются на плагины
// ресурсам нужны уникальные имена, чтобы плагины можно было использовать несколько раз
// они объявляются в форме: 'resource "plugin_name" "unique_name" {}'
// их выходные данные будут доступны другим ресурсам в форме unique_name.*
// пример: nmap.443
resource "nmap" "nmap" {
host = "${var.target_host}"
plugin_enabled = "true"
}
resource "sslscan" "sslscan" {
host = "${var.target_host}"
plugin_enabled = "${nmap.443 == "open"}"
}
Запуск плагина для каждого элемента списка:
variable "target_host" {
type = "string"
}
resource "nslookup" "nslookup" {
dns_server = "8.8.4.4"
host = "${var.target_host}"
}
resource "metasploit" "metasploit" {
for_each = "${nslookup.ip_address}"
exploit = "auxiliary/scanner/portscan/tcp"
options = {
RHOSTS = "${each.key}/32"
INTERFACE = "eth0"
}
}
Сложная конфигурация, объединяющая for_each с вложенными значениями:
variable "target_host" {
type = "string"
}
resource "nslookup" "nslookup" {
dns_server = "8.8.4.4"
host = "${var.target_host}"
}
resource "nmap" "nmap" {
for_each = "${nslookup.ip_address}"
host = "${each.key}"
}
// для каждого IP проверяем, открыт ли 25 порт по данным nmap
// если да, запускаем сканер smtp_enum из metasploit
resource "metasploit" "metasploit" {
for_each = "${nslookup.ip_address}"
exploit = "auxiliary/scanner/smtp/smtp_enum"
options = {
RHOSTS = "${each.key}"
}
plugin_enabled = "${nmap["${each.key}"].25 == "open"}"
}
Доступно несколько форматов вывода, причём одновременно можно выбрать более одного.
Установка переменных DECKER_OUTPUTS_JSON или DECKER_OUTPUTS_XML в "true" приведёт к выводу файлов в формате json и xml соответственно.
.json в дополнение к обычному тексту: export DECKER_OUTPUTS_JSON="true".xml в дополнение к обычному тексту: export DECKER_OUTPUTS_XML="true"Моя подруга Courtney пришла на помощь, когда я мучительно подбирал имя, и нашла decker в глоссарии научно-фантастических терминов... а звучало это круто.
Будущий взломщик; эксперт по программному обеспечению, умеющий манипулировать киберпространством, особенно обходить меры безопасности.
Монтируются две директории:
decker-reports, куда decker будет выводить файл для каждого выполненного плагина. Имя файла будет {unique_resource_name}.report.txt.examples, содержащий конфигурационные файлы decker. Монтирование этого тома позволяет писать конфиги локально в любимом редакторе и запускать их внутри контейнера.Передаётся одна переменная окружения:
DECKER_TARGET_HOSTНа неё ссылаются в конфигурационных файлах как {var.target_host}. Decker перебирает все переменные окружения, начинающиеся с DECKER_*, отбрасывает префикс и приводит остаток к нижнему регистру.
docker run -it --rm \
-v "$(pwd)/decker-reports/":/tmp/reports/ \
-v "$(pwd)/examples/":/decker-config/ \
-e DECKER_TARGET_HOST=example.com \
stevenaldinger/decker:kali decker ./decker-config/example.hcl
Когда decker завершит выполнение конфигурации, результаты можно посмотреть в ./decker-reports.
Вероятно, вам потребуется задать директорию для отчётов decker с помощью переменной окружения DECKER_REPORTS_DIR.
Подойдёт что-то вроде этого. Просто убедитесь, что указанный каталог существует.
export DECKER_REPORTS_DIR="$HOME/decker-reports"
Также нужно будет указать целевой хост, если вы запускаете один из примеров конфигурации.
export DECKER_TARGET_HOST="<введите имя хоста>"
Затем просто запустите конфигурационный файл. Перейдите в корневой каталог этого репозитория и выполните:
./decker ./examples/example.hcl
Мы очень приветствуем и ценим вклад в проект. Рекомендации см. в docs/contributions.md.
Для удобства рекомендуется использовать docker для разработки. Это гарантирует, что все зависимости будут установлены и готовы к работе.
Обзор структуры Go-кода см. в разделе Структура директорий ниже.
make docker_buildmake docker_run (запустит докер-контейнер и откроет интерактивную bash-сессию)dep ensure -vmake build_allmake runВыполните make init, чтобы добавить скрипт pre-commit, который будет запускать линтер и тесты при каждом коммите.
Сам Decker — это лишь фреймворк, который читает конфигурационные файлы, определяет зависимости в них и запускает плагины в порядке, гарантирующем, что плагины, зависящие от других (выходные данные одного плагина являются входными для другого), выполняются после тех, от кого они зависят.
Настоящая мощь decker исходит от плагинов. Разработка плагина может быть настолько простой или сложной, насколько вы пожелаете, при условии, что конечным результатом будет файл .so, содержащий скомпилированный код плагина, и файл .hcl в той же директории, объявляющий входные данные, которые ожидаются от пользователя.
Ознакомьтесь с docs/building_plugins.md, чтобы начать работу над первым плагином. Это займёт всего несколько минут, чтобы запустить плагин decker с выводом "Hello World".
По умолчанию плагины ожидаются в директории относительно расположения бинарного файла decker по пути <decker binary>/internal/app/decker/plugins/<plugin name>/<plugin name>.so. Дополнительные пути можно добавить, задав переменную окружения DECKER_PLUGIN_DIRS. Путь по умолчанию всё равно будет использоваться, если задана DECKER_PLUGIN_DIRS.
Пример: export DECKER_PLUGIN_DIRS="/path/to/my/plugins:/additional/path/to/plugins"
Рядом с файлом .so по пути <decker binary>/internal/app/decker/plugins/<plugin name>/<plugin name>.hcl должен находиться HCL-файл, определяющий его входные и выходные данные. В настоящее время поддерживаются только входные параметры типов string, list и map. Каждый входной параметр должен иметь блок input, который выглядит так:
input "my_input" {
type = "string"
default = "some default value"
}
.
├── build
│ ├── ci/
│ └── package/
├── cmd
│ ├── decker
│ │ └── main.go
│ └── README.md
├── deployments/
├── docs/
├── examples
│ └── example.hcl
├── githooks
│ ├── pre-commit
├── Gopkg.toml
├── internal
│ ├── app
│ │ └── decker
│ │ └── plugins
│ │ ├── a2sv
│ │ │ ├── a2sv.hcl
│ │ │ ├── main.go
│ │ │ └── README.md
│ │ └── ...
│ │ ├── main.go
│ │ ├── README.md
│ │ └── xxx.hcl
│ ├── pkg
│ │ ├── dependencies/
│ │ ├── gocty/
│ │ ├── hcl/
│ │ ├── paths/
│ │ ├── plugins/
│ │ └── reports/
│ └── README.md
├── LICENSE
├── Makefile
├── README.md
└── scripts
├── build-plugins.sh
└── README.md
resource в файле и запустить плагины с указанными входными параметрами.decker. Если вы используете kali докер-образ (stevenaldinger/decker:kali), все зависимости для всех конфигурационных файлов должны быть установлены, и всё должно работать гладко.decker