| name | infrastructure-checklist |
| description | Checklist for passive infrastructure security assessment. Covers SSL/TLS, DNS, subdomains, server fingerprinting, CDN/WAF detection, port scanning, and exposed paths. |
| allowed-tools | Read, Grep, Glob, WebFetch, Bash(curl:*), Bash(dig:*), Bash(nmap:*), Bash(python:*), Bash(python3:*), Bash(openssl:*), Bash(timeout:*), Bash(grep:*), Bash(head:*), Bash(tail:*), Bash(echo:*), Bash(cat:*), Bash(jq:*) |
Infrastructure Security Assessment Checklist
This checklist provides a systematic approach to passive infrastructure security assessment. Replace TARGET with the actual domain or IP address being assessed.
1. SSL/TLS Configuration
Use SSL Labs API:
curl -s "https://api.ssllabs.com/api/v3/analyze?host=TARGET&publish=off&startNew=on"
curl -s "https://api.ssllabs.com/api/v3/analyze?host=TARGET"
Key fields to extract from response:
- Overall grade (A+, A, B, C, F)
- Protocol support (TLS 1.0, 1.1, 1.2, 1.3)
- Certificate chain validity
- Certificate expiration date
- Key exchange strength
- Cipher suite strength
- Known vulnerabilities (Heartbleed, POODLE, ROBOT, etc.)
Alternative with curl:
curl -vI https://TARGET 2>&1 | grep -E "SSL connection|subject:|expire|issuer:|TLSv"
Quick check with openssl (if available):
echo | openssl s_client -connect TARGET:443 -servername TARGET 2>/dev/null | openssl x509 -noout -dates -subject -issuer
2. DNS Records
dig TARGET A +short
dig TARGET AAAA +short
dig TARGET MX +short
dig TARGET NS +short
dig TARGET TXT +short
dig _dmarc.TARGET TXT +short
dig TARGET TXT +short | grep "v=spf1"
dig default._domainkey.TARGET TXT +short
dig selector1._domainkey.TARGET TXT +short
dig selector2._domainkey.TARGET TXT +short
dig google._domainkey.TARGET TXT +short
dig TARGET +dnssec +short
dig TARGET CAA +short
What to check:
- SPF present and restrictive (ends with
-all not ~all or +all)
- DMARC present with
p=reject or p=quarantine (not p=none in production)
- DKIM configured
- DNSSEC enabled
- CAA records limiting certificate issuance
3. Subdomain Enumeration
Certificate transparency via crt.sh:
curl -s "https://crt.sh/?q=%.TARGET&output=json" | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
domains = set()
for entry in data:
for name in entry.get('name_value', '').split('\n'):
name = name.strip().lstrip('*.')
if name:
domains.add(name)
for d in sorted(domains):
print(d)
except: pass
" 2>/dev/null
For each discovered subdomain, check if it resolves:
dig SUBDOMAIN A +short
Look for: staging/dev/test subdomains, admin panels, internal tools.
4. Server Fingerprinting
curl -sI https://TARGET | grep -i "server\|x-powered-by\|x-aspnet-version\|x-generator\|x-drupal\|x-wordpress"
CDN/WAF detection:
curl -sI https://TARGET | grep -i "cf-ray\|x-cdn\|x-cache\|via\|x-amz\|x-azure\|x-served-by\|x-varnish\|x-fastly\|x-akamai\|x-sucuri\|x-fw-hash"
Common CDN/WAF signatures:
| Header/Value | Provider |
|---|
| cf-ray | Cloudflare |
| x-amz-* | AWS CloudFront |
| x-azure-ref | Azure CDN |
| x-fastly-request-id | Fastly |
| x-sucuri-* | Sucuri WAF |
| x-fw-hash | Wordfence |
| Server: AkamaiGHost | Akamai |
5. Port Scanning
Top 20 TCP ports (passive, polite timing):
nmap -sT --top-ports 20 -T2 --max-retries 1 --host-timeout 60s TARGET
Note: T2 is polite timing, max-retries 1 minimizes traffic. Only TCP connect scan (no SYN/stealth). If nmap is not available, test common ports with curl:
for port in 21 22 23 25 53 80 110 143 443 445 993 995 3306 3389 5432 8080 8443 8888; do
timeout 3 bash -c "echo >/dev/tcp/TARGET/$port" 2>/dev/null && echo "OPEN: $port"
done
Flag unexpected open ports.
6. Exposed Paths
Probe common sensitive paths:
for path in /.git/HEAD /.git/config /.env /.env.local /.env.production /wp-admin/ /wp-login.php /phpinfo.php /server-status /server-info /.htaccess /web.config /crossdomain.xml /.well-known/security.txt /sitemap.xml /robots.txt /backup/ /admin/ /debug/ /console/ /.DS_Store /Thumbs.db /.svn/entries /wp-config.php.bak /config.php.bak; do
code=$(curl -sI "https://TARGET${path}" -o /dev/null -w "%{http_code}")
[ "$code" != "404" ] && [ "$code" != "000" ] && echo "$code $path"
done
Special handling:
.git/HEAD: if 200, try to read (git repo exposed!)
.env: if 200, environment secrets exposed!
security.txt: informational, good practice to have
7. SecurityHeaders.com Check
Severity Assessment Guide
| Finding | Severity |
|---|
| TLS < 1.2 supported | Critical |
| Expired certificate | Critical |
| .git/HEAD exposed | Critical |
| .env exposed | Critical |
| SSL Labs grade C or lower | High |
| Known SSL vulnerabilities (Heartbleed, etc.) | Critical |
| Missing SPF/DMARC | Medium |
| SPF with ~all or +all | High |
| DMARC with p=none | Medium |
| Server banner with exact version | Low |
| Open unnecessary ports | Medium |
| Staging/dev subdomains publicly accessible | Medium |
| Missing DNSSEC | Low |
| Missing CAA records | Low |
| Missing security.txt | Info |
Finding Report Format
Each finding MUST follow this format:
### [SEVERITY] Problem title
- **URL/Evidence:** specific URL, header, code fragment
- **Risk:** technical + business risk description
- **Recommendation:** what to do (with config/code example)
- **Verification:** how to confirm the fix
- **Owner:** Dev / DevOps / Security