# Automation & Scripting

Templates and patterns for automating penetration testing tasks.

## Bash Scripting

### Reconnaissance Automation

```bash
#!/bin/bash
# recon.sh - Basic recon automation

TARGET=$1
OUTPUT_DIR="./recon/$TARGET"

if [ -z "$TARGET" ]; then
    echo "Usage: $0 <domain>"
    exit 1
fi

mkdir -p "$OUTPUT_DIR"

echo "[*] Starting recon for $TARGET"

# Subdomain enumeration
echo "[*] Subdomain enumeration..."
subfinder -d "$TARGET" -silent | tee "$OUTPUT_DIR/subdomains.txt"
amass enum -passive -d "$TARGET" >> "$OUTPUT_DIR/subdomains.txt"
sort -u "$OUTPUT_DIR/subdomains.txt" -o "$OUTPUT_DIR/subdomains.txt"

# Resolve subdomains
echo "[*] Resolving subdomains..."
cat "$OUTPUT_DIR/subdomains.txt" | httpx -silent | tee "$OUTPUT_DIR/alive.txt"

# Port scanning
echo "[*] Port scanning..."
naabu -l "$OUTPUT_DIR/subdomains.txt" -silent | tee "$OUTPUT_DIR/ports.txt"

# Screenshot
echo "[*] Taking screenshots..."
cat "$OUTPUT_DIR/alive.txt" | gowitness file -f - -P "$OUTPUT_DIR/screenshots"

echo "[*] Recon complete. Results in $OUTPUT_DIR"
```

### Parallel Processing

```bash
#!/bin/bash
# parallel_scan.sh - Parallel URL scanning

URLS_FILE=$1
THREADS=${2:-10}

# Using xargs
cat "$URLS_FILE" | xargs -P "$THREADS" -I {} sh -c 'curl -s -o /dev/null -w "%{http_code} {}\n" "{}"'

# Using GNU Parallel
cat "$URLS_FILE" | parallel -j "$THREADS" "curl -s -o /dev/null -w '%{http_code} {}\n' {}"

# Custom function with parallel
scan_url() {
    url=$1
    status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
    echo "$status $url"
}
export -f scan_url

cat "$URLS_FILE" | parallel -j "$THREADS" scan_url {}
```

### Bruteforce Helper

```bash
#!/bin/bash
# brute_dirs.sh - Directory bruteforce with progress

TARGET=$1
WORDLIST=${2:-"/usr/share/seclists/Discovery/Web-Content/common.txt"}
THREADS=${3:-50}

ffuf -u "$TARGET/FUZZ" \
     -w "$WORDLIST" \
     -t "$THREADS" \
     -mc 200,204,301,302,307,401,403 \
     -o results.json \
     -of json

# Parse results
jq -r '.results[] | "\(.status) \(.url)"' results.json
```

## Python Scripts

### HTTP Request Template

```python
#!/usr/bin/env python3
"""
http_template.py - Basic HTTP request template
"""

import requests
import argparse
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed

def make_request(url, method='GET', data=None, headers=None, timeout=10):
    """Make HTTP request and return response"""
    try:
        if method.upper() == 'GET':
            resp = requests.get(url, headers=headers, timeout=timeout, verify=False)
        elif method.upper() == 'POST':
            resp = requests.post(url, data=data, headers=headers, timeout=timeout, verify=False)
        return {
            'url': url,
            'status': resp.status_code,
            'length': len(resp.content),
            'content': resp.text[:500]
        }
    except Exception as e:
        return {'url': url, 'error': str(e)}

def main():
    parser = argparse.ArgumentParser(description='HTTP request tool')
    parser.add_argument('-u', '--url', help='Single URL to test')
    parser.add_argument('-l', '--list', help='File with URLs')
    parser.add_argument('-t', '--threads', type=int, default=10, help='Number of threads')
    parser.add_argument('-m', '--method', default='GET', help='HTTP method')
    args = parser.parse_args()

    urls = []
    if args.url:
        urls = [args.url]
    elif args.list:
        with open(args.list) as f:
            urls = [line.strip() for line in f if line.strip()]
    else:
        urls = [line.strip() for line in sys.stdin if line.strip()]

    with ThreadPoolExecutor(max_workers=args.threads) as executor:
        futures = {executor.submit(make_request, url, args.method): url for url in urls}
        for future in as_completed(futures):
            result = future.result()
            if 'error' not in result:
                print(f"[{result['status']}] {result['url']} ({result['length']} bytes)")
            else:
                print(f"[ERR] {result['url']}: {result['error']}")

if __name__ == '__main__':
    import urllib3
    urllib3.disable_warnings()
    main()
```

### SQLi Checker

```python
#!/usr/bin/env python3
"""
sqli_check.py - Basic SQL injection detection
"""

import requests
import re
from urllib.parse import urlparse, parse_qs, urlencode

SQLI_PAYLOADS = [
    "'",
    "''",
    "'--",
    "' OR '1'='1",
    "' OR '1'='1'--",
    "1' ORDER BY 1--",
    "1' ORDER BY 10--",
]

SQL_ERRORS = [
    r"SQL syntax.*MySQL",
    r"Warning.*mysql_",
    r"MySqlException",
    r"valid MySQL result",
    r"PostgreSQL.*ERROR",
    r"Warning.*pg_",
    r"ORA-\d{5}",
    r"Oracle error",
    r"SQLite3::SQLException",
    r"Microsoft SQL Server",
    r"ODBC SQL Server Driver",
    r"SQLServer JDBC Driver",
    r"mssql_query",
]

def check_sqli(url):
    """Test URL for SQL injection"""
    parsed = urlparse(url)
    params = parse_qs(parsed.query)
    
    results = []
    for param_name in params:
        for payload in SQLI_PAYLOADS:
            test_params = params.copy()
            test_params[param_name] = [payload]
            test_query = urlencode(test_params, doseq=True)
            test_url = f"{parsed.scheme}://{parsed.netloc}{parsed.path}?{test_query}"
            
            try:
                resp = requests.get(test_url, timeout=10, verify=False)
                for pattern in SQL_ERRORS:
                    if re.search(pattern, resp.text, re.IGNORECASE):
                        results.append({
                            'url': test_url,
                            'param': param_name,
                            'payload': payload,
                            'error_pattern': pattern
                        })
                        break
            except:
                pass
    
    return results

if __name__ == '__main__':
    import sys
    url = sys.argv[1] if len(sys.argv) > 1 else input("URL: ")
    results = check_sqli(url)
    for r in results:
        print(f"[!] Potential SQLi: {r['param']} with payload: {r['payload']}")
```

### Subdomain Takeover Checker

```python
#!/usr/bin/env python3
"""
takeover_check.py - Check for subdomain takeover
"""

import requests
import dns.resolver
import sys

FINGERPRINTS = {
    'GitHub Pages': ['There isn\'t a GitHub Pages site here'],
    'Heroku': ['No such app', 'herokucdn.com'],
    'AWS S3': ['NoSuchBucket', 'The specified bucket does not exist'],
    'Azure': ['404 Web Site not found'],
    'Shopify': ['Sorry, this shop is currently unavailable'],
    'Fastly': ['Fastly error: unknown domain'],
    'Pantheon': ['404 error unknown site'],
    'Zendesk': ['Help Center Closed'],
    'Tumblr': ['There\'s nothing here.', 'Whatever you were looking for'],
}

def check_cname(domain):
    """Get CNAME record for domain"""
    try:
        answers = dns.resolver.resolve(domain, 'CNAME')
        return str(answers[0].target).rstrip('.')
    except:
        return None

def check_takeover(domain):
    """Check if domain is vulnerable to takeover"""
    cname = check_cname(domain)
    if not cname:
        return None
    
    try:
        resp = requests.get(f'http://{domain}', timeout=10, verify=False)
        content = resp.text
        
        for service, patterns in FINGERPRINTS.items():
            for pattern in patterns:
                if pattern.lower() in content.lower():
                    return {
                        'domain': domain,
                        'cname': cname,
                        'service': service,
                        'vulnerable': True
                    }
    except:
        pass
    
    return None

if __name__ == '__main__':
    import urllib3
    urllib3.disable_warnings()
    
    domains = [line.strip() for line in sys.stdin] if not sys.stdin.isatty() else sys.argv[1:]
    
    for domain in domains:
        result = check_takeover(domain)
        if result:
            print(f"[!] {result['domain']} -> {result['cname']} ({result['service']})")
```

## Tool Chaining

### Recon Pipeline

```bash
#!/bin/bash
# Full recon pipeline

TARGET=$1
THREADS=50

echo "[*] Running full recon pipeline for $TARGET"

# Phase 1: Subdomain enum
echo "[*] Phase 1: Subdomain enumeration"
subfinder -d "$TARGET" -silent | anew subs.txt
assetfinder --subs-only "$TARGET" | anew subs.txt
amass enum -passive -d "$TARGET" | anew subs.txt

# Phase 2: Resolve and probe
echo "[*] Phase 2: HTTP probing"
cat subs.txt | httpx -silent -threads $THREADS | tee alive.txt

# Phase 3: Port scanning
echo "[*] Phase 3: Port scanning"
cat subs.txt | naabu -silent -top-ports 1000 | tee ports.txt

# Phase 4: Technology detection
echo "[*] Phase 4: Technology detection"
cat alive.txt | httpx -silent -tech-detect -json | jq -r '"\(.url) | \(.tech | join(", "))"' | tee tech.txt

# Phase 5: Vulnerability scanning
echo "[*] Phase 5: Vulnerability scanning"
cat alive.txt | nuclei -silent -severity medium,high,critical | tee vulns.txt

echo "[*] Pipeline complete!"
```

### Web Attack Pipeline

```bash
#!/bin/bash
# Web attack automation

URL=$1

echo "[*] Starting web attack pipeline for $URL"

# Directory fuzzing
echo "[*] Directory fuzzing..."
ffuf -u "$URL/FUZZ" -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -mc 200,301,302,403 -o dirs.json -of json -s

# Parameter discovery
echo "[*] Parameter discovery..."
arjun -u "$URL" --stable -oT params.txt

# JS file analysis
echo "[*] Collecting JavaScript files..."
katana -u "$URL" -jc -d 2 -silent | grep "\.js$" | tee js_files.txt

# Extract secrets from JS
echo "[*] Analyzing JS for secrets..."
cat js_files.txt | while read js; do
    curl -s "$js" | grep -oE "(api[_-]?key|secret|token|password|auth)['\"]?\s*[:=]\s*['\"]?[a-zA-Z0-9_-]+"
done | tee secrets.txt

# Nuclei scan
echo "[*] Running nuclei..."
echo "$URL" | nuclei -severity medium,high,critical -o nuclei_results.txt

echo "[*] Web attack pipeline complete!"
```

## One-Liners Collection

### Subdomain Enumeration

```bash
# All-in-one subdomain enum
(subfinder -d $1 -silent; assetfinder --subs-only $1; amass enum -passive -d $1 2>/dev/null) | sort -u

# With resolution
subfinder -d $1 -silent | dnsx -silent | httpx -silent

# Extract subdomains from certificate transparency
curl -s "https://crt.sh/?q=%.$1&output=json" | jq -r '.[].name_value' | sed 's/\*\.//g' | sort -u
```

### HTTP Analysis

```bash
# Status codes for URL list
cat urls.txt | httpx -status-code -silent -no-color

# Extract URLs from page
curl -s $URL | grep -oP 'href="\K[^"]+' | sort -u

# Find all endpoints in JS files
cat js_files.txt | xargs -I{} curl -s {} | grep -oP '["\']/[a-zA-Z0-9_/?=&-]+["\']' | tr -d '"'"'" | sort -u
```

### Quick Vulnerability Checks

```bash
# CORS check
curl -s -I -H "Origin: https://evil.com" "$URL" | grep -i "access-control"

# Header injection
curl -s -I "$URL/%0d%0aX-Injected:%20header" | grep -i "x-injected"

# Open redirect
curl -s -o /dev/null -w "%{redirect_url}" "$URL?next=https://evil.com"

# XSS reflection check
curl -s "$URL?q=<script>alert(1)</script>" | grep -i "<script>alert"
```

### Credential Hunting

```bash
# Search for secrets in files
grep -rE "(password|secret|api_key|token)\s*[:=]\s*['\"][^'\"]+['\"]" .

# Git secrets
git log -p | grep -E "(password|secret|api_key|token)\s*[:=]"

# AWS keys in files
grep -rE "AKIA[0-9A-Z]{16}" .
```

## Workflow Examples

### Bug Bounty Automation

```bash
#!/bin/bash
# bb_recon.sh - Bug bounty recon workflow

DOMAIN=$1
DATE=$(date +%Y%m%d)
OUTDIR="bb_recon_${DOMAIN}_${DATE}"

mkdir -p "$OUTDIR"
cd "$OUTDIR"

# Asset discovery
echo "[*] Asset discovery..."
subfinder -d "$DOMAIN" -silent | httpx -silent > live_hosts.txt

# Technology fingerprinting
echo "[*] Tech fingerprinting..."
cat live_hosts.txt | httpx -silent -tech-detect -json > tech.json

# Nuclei vulnerability scan
echo "[*] Vulnerability scanning..."
nuclei -l live_hosts.txt -severity medium,high,critical -o vulns.txt

# Generate report
echo "# Recon Report for $DOMAIN" > report.md
echo "Date: $DATE" >> report.md
echo "" >> report.md
echo "## Live Hosts: $(wc -l < live_hosts.txt)" >> report.md
echo "## Vulnerabilities Found: $(wc -l < vulns.txt)" >> report.md

echo "[*] Complete! Check $OUTDIR/report.md"
```

## Related Topics

* [Tool Index](/others/tool-index.md) - Tool references
* [Wordlist Reference](/others/wordlist-reference.md) - Wordlists
* [Lab Setup Guide](/others/lab-setup-guide.md) - Practice environments


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.pentest-book.com/others/automation-scripting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
