Files
sif/modules/recon/terraform-state-exposure.yaml
TigahandGitHub 1e47b6547e feat(modules): add terraform, kubeconfig and compose exposure modules (#201)
modules/recon/terraform-state-exposure.yaml flags an exposed terraform state
file on the terraform_version key paired with a state structure key, then
extracts the version. the structure key keeps a document that merely mentions
terraform_version from matching.

modules/recon/kubeconfig-exposure.yaml flags an exposed kubeconfig on the
kind: Config marker paired with a cluster or credential key, then extracts the
cluster api endpoint. it catches an exec auth kubeconfig with no embedded key
since the cluster block alone is a leak.

modules/recon/docker-compose-exposure.yaml flags an exposed compose file on the
services key paired with a service definition key, then extracts the first
image reference to surface the stack and its versions.

each module pairs a unique marker with a structure key and rejects an html
body, so a page that only names the marker is not a leak.

internal/modules/infra_config_exposure_test.go drives the three modules end to
end through ExecuteHTTPModule and asserts the leak alongside the near misses a
strict review wants pinned: a bare terraform_version mention, a bare
kind: Config mention, a bare services key, an html page carrying the markers, a
plain 200 body and a 404, none of which may match.

verify: go test ./internal/modules, each marker, structure gate, guard and
extractor proven to bite (break -> red, restore -> green).
2026-06-22 19:52:16 -07:00

57 lines
1.1 KiB
YAML

# Terraform State Exposure Detection Module
id: terraform-state-exposure
info:
name: Terraform State Exposure
author: sif
severity: high
description: Detects an exposed terraform state file that leaks infrastructure secrets and resource attributes
tags: [terraform, iac, state, secrets, exposure, recon]
type: http
http:
method: GET
paths:
- "{{BaseURL}}/terraform.tfstate"
- "{{BaseURL}}/terraform.tfstate.backup"
- "{{BaseURL}}/.terraform/terraform.tfstate"
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- '"terraform_version"'
- type: word
part: body
condition: or
words:
- '"lineage"'
- '"serial"'
- '"resources"'
- type: word
part: body
negative: true
condition: or
words:
- "<!DOCTYPE"
- "<!doctype"
- "<html"
- "<HTML"
- "<head>"
- "<title>"
extractors:
- type: regex
name: terraform_version
part: body
regex:
- '"terraform_version"\s*:\s*"([0-9]+\.[0-9]+\.[0-9]+)'
group: 1