
Framework declarativo de orquestração de testes de penetração
Decker é um framework de orquestração de testes de penetração. Ele utiliza a Linguagem de Configuração HashiCorp 2 (a mesma linguagem de configuração do Terraform) para permitir testes de penetração como código de forma declarativa, de modo que seus testes possam ser versionados, compartilhados, reutilizados e colaborados com sua equipe ou comunidade.
Exemplo de um arquivo de configuração do decker:
// variables are pulled from environment
// ex: DECKER_TARGET_HOST
// they will be available throughout the config files as var.*
// ex: ${var.target_host}
variable "target_host" {
type = "string"
}
// resources refer to plugins
// resources need unique names so plugins can be used more than once
// they are declared with the form: 'resource "plugin_name" "unique_name" {}'
// their outputs will be available to others using the form unique_name.*
// ex: nmap.443
resource "nmap" "nmap" {
host = "${var.target_host}"
plugin_enabled = "true"
}
resource "sslscan" "sslscan" {
host = "${var.target_host}"
plugin_enabled = "${nmap.443 == "open"}"
}
Execute um plugin para cada item em uma lista:
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"
}
}
Configuração complexa combinando for_each com valores aninhados:
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}"
}
// for each IP, check if nmap found port 25 open.
// if yes, run metasploit's smtp_enum scanner
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"}"
}
Vários formatos de saída estão disponíveis e mais de um pode ser selecionado ao mesmo tempo.
Definir DECKER_OUTPUTS_JSON ou DECKER_OUTPUTS_XML como "true" produzirá arquivos formatados em json e xml, respectivamente.
.json além do texto simples: export DECKER_OUTPUTS_JSON="true".xml além do texto simples: export DECKER_OUTPUTS_XML="true"Meu amigo Courtney veio em meu socorro quando eu estava lutando para encontrar um nome e encontrou decker em um glossário de palavras de ficção científica... e soou legal.
Um futuro cracker; um especialista em software habilidoso em manipular o ciberespaço, especialmente em contornar precauções de segurança.
Dois volumes são montados:
decker-reports onde o decker irá gerar um arquivo para cada plugin executado. O nome do arquivo será {unique_resource_name}.report.txt.examples contendo arquivos de configuração do decker. Montar este volume permite que você escreva configurações localmente usando seu editor favorito e ainda as execute dentro do contêiner.Uma variável de ambiente é passada:
DECKER_TARGET_HOSTEsta é referenciada nos arquivos de configuração como {var.target_host}. O Decker percorrerá todas as variáveis de ambiente chamadas DECKER_*, removendo o prefixo e definindo o restante em minúsculas.
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
Quando o decker terminar de executar a configuração, procure em ./decker-reports pelas saídas.
Você provavelmente vai querer definir o diretório para onde o decker escreve os relatórios usando a variável de ambiente DECKER_REPORTS_DIR.
Algo assim seria apropriado. Apenas certifique-se de que o que você definir seja um diretório existente.
export DECKER_REPORTS_DIR="$HOME/decker-reports"
Você também precisará definir um host alvo se estiver executando um dos arquivos de configuração de exemplo.
export DECKER_TARGET_HOST="<insert hostname here>"
Então basta executar um arquivo de configuração. Mude para o diretório raiz deste repositório e execute:
./decker ./examples/example.hcl
Contribuições são muito bem-vindas e apreciadas. Veja docs/contributions.md para diretrizes.
Usar Docker para desenvolvimento é recomendado para uma experiência tranquila. Isso garante que todas as dependências estejam instaladas e prontas para uso.
Consulte Estrutura de Diretórios abaixo para uma visão geral do código Go.
make docker_buildmake docker_run (iniciará o contêiner Docker e abrirá uma sessão bash interativa)dep ensure -vmake build_allmake runExecute make init para adicionar um script pre-commit que executará linting e testes em cada commit.
O Decker em si é apenas um framework que lê arquivos de configuração, determina dependências nos arquivos de configuração e executa plugins em uma ordem que garante que plugins com dependências de outros plugins (saída de um plugin sendo entrada para outro) sejam executados após aqueles dos quais dependem.
O verdadeiro poder do decker vem dos plugins. Desenvolver um plugin pode ser tão simples ou complexo quanto você quiser, desde que o resultado final seja um arquivo .so contendo o código do plugin compilado e um arquivo .hcl no mesmo diretório declarando as entradas que o plugin espera que o usuário configure.
Confira docs/building_plugins.md para começar com seu primeiro plugin. Deve levar apenas alguns minutos para colocar um plugin decker "Hello World" em funcionamento.
Por padrão, espera-se que os plugins estejam em um diretório relativo ao local onde o binário do decker está, em <decker binary>/internal/app/decker/plugins/<plugin name>/<plugin name>.so. Caminhos adicionais podem ser adicionados definindo a variável de ambiente DECKER_PLUGIN_DIRS. O caminho padrão do plugin ainda será usado se DECKER_PLUGIN_DIRS estiver definido.
Exemplo: export DECKER_PLUGIN_DIRS="/path/to/my/plugins:/additional/path/to/plugins"
Deve haver um arquivo HCL ao lado do arquivo .so em <decker binary>/internal/app/decker/plugins/<plugin name>/<plugin name>.hcl que define suas entradas e saídas. Atualmente, apenas entradas do tipo string, list e map são suportadas. Cada entrada deve ter um bloco input parecido com este:
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 do arquivo e executar os plugins com as entradas especificadas.decker. Se você usar a imagem docker kali (stevenaldinger/decker:kali), todas as dependências devem estar instaladas para todos os arquivos de configuração e as coisas devem funcionar sem problemas.decker, arquivos de configuração, arquivos de configuração de plugin e relatórios gerados.