Files
P-Aimon-Pen-ROFMAD/workflow-example.yaml
2026-06-18 15:03:00 +02:00

229 lines
11 KiB
YAML
Executable File

specific_actions:
# ============================================================================
# EXAMPLE A — Port-based condition (well-known, stable ports)
# Use contains: when you know the port never changes in practice.
# Single spawn per host — no fan-out.
# ============================================================================
- name: "smb_example"
condition:
contains: "445 AND 139" # must have BOTH ports open
# contains: "80 OR 443" # must have ANY of these ports open
# equals: "22" # must have EXACTLY this one port (rare)
has_tag: "smb AND Windows" # tag AND logic
# has_tag: "web OR database" # tag OR logic
has_not_tag: "anonymous-smb" # skip if already tagged (avoids re-running)
command: "nxc smb {{IP}} -u '' -p '' --shares"
timeout_s: 120
tags:
- pattern: "STATUS_SUCCESS"
tag: "anonymous-smb"
- pattern: "SMB.*signing.*False"
tag: "smb-signing-disabled"
- pattern: "(?i)domain.*corp" # (?i) = case-insensitive match
tag: "domain-corp-member"
- pattern: "VULNERABLE.*(MS17-010|EternalBlue)"
tag: "vulnerable-ms17-010"
# ============================================================================
# EXAMPLE B — Service-based condition: fires once per matching service instance
# has_service: "<single-name>" implies per-instance fan-out automatically.
# One task per port nmap identified as that service — handles non-standard ports
# and multiple simultaneous instances (e.g. MSSQL named instances).
# {{SERVICE_PORT}} resolves to the current instance's port.
# ============================================================================
- name: "mssql_example"
condition:
has_service: "mssql" # fires once per port nmap identified as mssql
# 1 instance → 1 task; 3 instances → 3 tasks
# {{SERVICE_PORT}} → the actual port for this instance
# works whether mssql is on 1433, 1434, or 49152
command: "nxc mssql {{IP}} -p {{SERVICE_PORT}} -u '' -p ''"
timeout_s: 60
tags:
- pattern: "\\[\\+\\]"
tag: "mssql-anonymous-access"
- name: "rdp_example"
condition:
has_service: "rdp" # catches 3389 AND any non-standard RDP port
command: "nxc rdp {{IP}} -p {{SERVICE_PORT}}"
timeout_s: 30
tags:
- pattern: "NLA.*False"
tag: "rdp-nla-disabled"
- name: "ftp_example"
condition:
has_service: "ftp"
command: "nxc ftp {{IP}} -p {{SERVICE_PORT}} -u 'anonymous' -p 'anonymous'"
timeout_s: 30
tags:
- pattern: "\\[\\+\\]"
tag: "ftp-anonymous-access"
# ============================================================================
# EXAMPLE C — HTTP service fan-out
# has_http_service: true fires once per discovered HTTP service on the host.
# {{HTTP_URL}} resolves to the correct http:// or https:// URL per iteration.
# Outputs stored as "nuclei_scan__80", "nuclei_scan__443", etc.
# ============================================================================
- name: "nuclei_scan"
condition:
has_http_service: true # fires per HTTP service; optional tags filter further
has_tag: "interesting" # host-level tag condition still applies
command: "nuclei -u {{HTTP_URL}} -silent -severity medium,high,critical"
timeout_s: 300
tags:
- pattern: "\\[critical\\]"
tag: "nuclei-critical"
- pattern: "\\[high\\]"
tag: "nuclei-high"
- name: "ffuf_fuzz"
condition:
has_http_service: true
command: "ffuf -u {{HTTP_URL}}/FUZZ -w /opt/wordlists/common.txt -mc 200,301,302 -s"
timeout_s: 600
- name: "curl_banner"
condition:
has_http_service: true
# Mix {{HTTP_PROTOCOL}} and {{HTTP_PORT}} freely
command: "curl -sk -I {{HTTP_PROTOCOL}}://{{IP}}:{{HTTP_PORT}}"
timeout_s: 15
tags:
- pattern: "(?i)X-Powered-By:"
tag: "http-powered-by-header"
# ============================================================================
# PLACEHOLDERS
# ============================================================================
# {{IP}} / {{ip}} / <IP> Target IP address
# {{PORT}} First port in the raw open port list
# (order-dependent — prefer {{PORT:service}})
# {{PORT:service}} First port where nmap identified 'service'
# Useful in single-spawn actions to cross-reference
# another service's port
# {{PORTS:service}} All ports running 'service', comma-separated
# e.g. "139,445" when smb runs on both
# {{URL}} / {{BASE_URL}} http(s)://IP:PORT (first HTTP service)
# {{PROTOCOL}} http or https (first HTTP service)
#
# Per-instance placeholders — available in has_service and has_http_service actions:
# {{SERVICE_PORT}} Port for the current instance
# {{SERVICE_PROTOCOL}} Protocol for the current instance (HTTP only)
# {{HTTP_URL}} http(s)://IP:PORT for the current HTTP instance
# {{HTTP_PORT}} Port for the current HTTP instance
# {{HTTP_PROTOCOL}} http or https for the current HTTP instance
# ============================================================================
# CONDITIONS — field reference
# ============================================================================
# contains: "445" Port 445 is in the open port list
# contains: "80 AND 443" Port 80 AND 443 both open
# contains: "80 OR 443" Port 80 OR 443 open
# equals: "22" ONLY port 22 open
# has_tag: "windows" Tag present in automated/manual/refined tags
# has_tag: "smb AND windows" Both tags present
# has_tag: "smb OR netbios" Either tag present
# has_not_tag: "anonymous-smb" Skip host if tag IS present (inverse gate)
# has_not_tag: "exploited AND owned" Skip if BOTH tags present
# has_not_tag: "low-value OR noise" Skip if EITHER tag present
# has_service: "mssql" nmap -sV identified mssql — fires per instance
# Single name only: AND/OR stays a boolean gate
# has_service: "rdp OR winrm" Either service present (single spawn, no fan-out)
# has_http_service: true/false HTTP service confirmed — fires per HTTP service
# reconnaissance_complete: true Always enforced — no need to specify
#
# All specified fields must pass simultaneously (AND between fields).
# OR/AND logic applies within a single field value only.
#
# Fan-out behaviour:
# has_service: "mssql" → 1 task per port running mssql (0 tasks if absent)
# has_http_service: true → 1 task per HTTP service (0 tasks if absent)
# all other conditions → single spawn per host
# ============================================================================
# SERVICE NAMES — after normalize_service_name() (use these in has_service:)
# Matching is exact, case-insensitive. "MSSQL" matches "mssql"; "sql" does NOT.
# ============================================================================
#
# Core Windows services:
# smb (nmap: microsoft-ds, cifs)
# mssql (nmap: ms-sql-s, ms-sql-m, ms-sql-monitor, ms-sql-ds)
# rdp (nmap: ms-wbt-server)
# winrm (nmap: wsman)
# kerberos (nmap: kerberos-sec)
# netbios (nmap: netbios-ssn, netbios-ns)
# rpc (nmap: msrpc, epmap, ncacn_http, ncacn_ip_tcp, msrpc-base)
# dns (nmap: domain)
#
# Common Linux/cross-platform (pass-through, already clean):
# ssh, ftp, http, https, smtp, pop3, imap, ldap, mysql, postgresql
# vnc, telnet, snmp, redis, mongodb, nfs, ntp
#
# Pass-through but worth knowing:
# rpcbind Unix portmapper (port 111) — intentionally NOT mapped to "rpc"
# (different tooling from Windows msrpc; use has_service: "rpcbind")
# oracle-tns Oracle TNS listener — clean identifier, no normalization needed
# ajp13 Tomcat AJP connector (port 8009) — clean identifier
#
# TLS variants — normalized to base service:
# ldaps → ldap | imaps → imap | smtps → smtp | pop3s → pop3 | ftps → ftp
# ssl/http → http | ssl/ldap → ldap (ssl/ prefix stripped automatically)
#
# HTTP on alternate ports:
# http-alt → http (use has_service: "http")
# http-proxy kept as-is — Squid/HAProxy, NOT generic http
#
# Niche/application-specific services (elasticsearch, squid, etc.):
# Use the action builder — workflow.yaml covers systematic services only
# ============================================================================
# HOW AUTOMATED TAGS ARE GENERATED FROM NMAP
# ============================================================================
# nmap -sV produces two distinct fields per port — both become automated tags:
#
# 1. service name → normalize_service_name() → short canonical tag
# Raw: "ms-sql-s" Tag: "mssql"
# Raw: "microsoft-ds" Tag: "smb"
# Raw: "ms-wbt-server" Tag: "rdp"
# See SERVICE NAMES section above for the full mapping table.
#
# 2. product string → lowercased → full-string tag (refined by hardcoded rules)
# nmap: product="Apache httpd" Tag: "apache" (hardcoded rule)
# nmap: product="nginx" Tag: "nginx" (hardcoded rule)
# nmap: product="Microsoft IIS httpd" Tag: "iis" (hardcoded rule)
# nmap: product="Squid http proxy" Tag: "squid http proxy" (no rule — stays as-is)
#
# Well-known products normalized by hardcoded rules (produces short tags):
# smb, rdp, winrm, dns, kerberos, ldap, rpc, mssql, iis, apache, nginx,
# tomcat, mysql, mariadb, postgresql, ssh
#
# Niche products (no hardcoded rule) — tag is the full product string lowercased.
# Target them in the action builder: browse available tags to find the exact value,
# or use has_service: for broader protocol-level matching.
#
# Examples:
# Squid proxy: has_service: "http-proxy" (all proxies)
# has_tag: "squid http proxy" (specifically Squid, via action builder)
# HAProxy: has_service: "http-proxy" (same service name)
# has_tag: "haproxy" (if nmap product is just "HAProxy")
# ============================================================================
# TAG PATTERN SYNTAX
# ============================================================================
# - Standard regex
# - Case-sensitive by default — prefix (?i) for case-insensitive
# - Matched against full stdout + stderr of the command
# - Multiple patterns are independent — each applies its own tag
# - Tags are written immediately after the action completes;
# subsequent actions can depend on them via has_tag: