Cheatsheet

Nikto web server scanner: techniques

intermediate va

Basic Usage #

Simple Web Server Scan #

bash
# Basic scan
nikto -h http://target.com

# Scan with HTTPS
nikto -h https://target.com

# Scan specific port
nikto -h http://target.com:8080

# Scan multiple hosts
nikto -h http://target1.com,http://target2.com

# Scan from file
echo "http://target1.com" > targets.txt
echo "http://target2.com" >> targets.txt
nikto -h targets.txt

Port and Protocol Options #

bash
# Scan specific port
nikto -h target.com -p 80,443,8080,8443

# Scan port range
nikto -h target.com -p 80-90

# Force SSL
nikto -h target.com -ssl

# Disable SSL
nikto -h target.com -nossl

# Use specific HTTP method
nikto -h target.com -method GET
nikto -h target.com -method POST

Authentication #

bash
# Basic authentication
nikto -h http://target.com -id username:password

# NTLM authentication
nikto -h http://target.com -id domain\\username:password

# Custom headers
nikto -h http://target.com -H "Authorization: Bearer token123"

# Cookie authentication
nikto -h http://target.com -H "Cookie: sessionid=abc123"

# Multiple headers
nikto -h http://target.com -H "Authorization: Bearer token" -H "X-API-Key: key123"

Advanced Scanning #

Tuning Options #

bash
# Scan specific categories
nikto -h target.com -Tuning 1    # Interesting File / Seen in logs
nikto -h target.com -Tuning 2    # Misconfiguration / Default File
nikto -h target.com -Tuning 3    # Information Disclosure
nikto -h target.com -Tuning 4    # Injection (XSS/Script/HTML)
nikto -h target.com -Tuning 5    # Remote File Retrieval - Inside Web Root
nikto -h target.com -Tuning 6    # Denial of Service
nikto -h target.com -Tuning 7    # Remote File Retrieval - Server Wide
nikto -h target.com -Tuning 8    # Command Execution - Remote Shell
nikto -h target.com -Tuning 9    # SQL Injection
nikto -h target.com -Tuning 0    # File Upload
nikto -h target.com -Tuning a    # Authentication Bypass
nikto -h target.com -Tuning b    # Software Identification
nikto -h target.com -Tuning c    # Remote Source Inclusion
nikto -h target.com -Tuning x    # Reverse Tuning Options (exclude)

# Multiple tuning options
nikto -h target.com -Tuning 1,2,3,4

# Exclude specific tests
nikto -h target.com -Tuning x6   # Exclude DoS tests

Plugin Management #

bash
# List available plugins
nikto -list-plugins

# Use specific plugins
nikto -h target.com -Plugins "apacheusers,cgi"

# Exclude plugins
nikto -h target.com -Plugins "@@DEFAULT" -Plugins "-outdated"

# Custom plugin directory
nikto -h target.com -plugindir /path/to/plugins

# Plugin-specific options
nikto -h target.com -Plugins "cgi(all)"
nikto -h target.com -Plugins "headers(verbose)"

Output and Reporting #

bash
# Save output to file
nikto -h target.com -o scan_results.txt

# Specify output format
nikto -h target.com -Format txt -o results.txt
nikto -h target.com -Format xml -o results.xml
nikto -h target.com -Format csv -o results.csv
nikto -h target.com -Format htm -o results.html
nikto -h target.com -Format json -o results.json

# Multiple output formats
nikto -h target.com -Format txt,xml,csv -o results

# Verbose output
nikto -h target.com -verbose

# Display only specific findings
nikto -h target.com -Display 1   # Show redirects
nikto -h target.com -Display 2   # Show cookies received
nikto -h target.com -Display 3   # Show all 200/OK responses
nikto -h target.com -Display 4   # Show URLs which require authentication
nikto -h target.com -Display V   # Verbose output
nikto -h target.com -Display E   # Debug output

Specialized Scanning #

SSL/TLS Testing #

bash
# SSL-specific scan
nikto -h https://target.com -ssl

# Test SSL ciphers
nikto -h https://target.com -Plugins "ssl"

# Ignore SSL certificate errors
nikto -h https://target.com -ssl -nossl

# Test specific SSL version
nikto -h https://target.com -ssl -sslversion 3

CGI and Script Testing #

bash
# CGI enumeration
nikto -h target.com -Plugins "cgi"

# Test all CGI directories
nikto -h target.com -Plugins "cgi(all)"

# Custom CGI directory
nikto -h target.com -Cgidirs "/scripts/,/cgi/,/custom-cgi/"

# Test for dangerous CGI scripts
nikto -h target.com -Tuning 8

Directory and File Discovery #

bash
# Test for common files
nikto -h target.com -Tuning 1,2

# Test for backup files
nikto -h target.com -Plugins "backup_files"

# Test for interesting files
nikto -h target.com -Plugins "interesting_files"

# Custom root directory
nikto -h target.com -root /app/

# Test multiple directories
nikto -h target.com -root /,/app/,/admin/

Database and Application Testing #

bash
# SQL injection tests
nikto -h target.com -Tuning 9

# Test for database files
nikto -h target.com -Plugins "database_files"

# Test for application-specific vulnerabilities
nikto -h target.com -Plugins "apache_expect_xss"
nikto -h target.com -Plugins "shellshock"
nikto -h target.com -Plugins "heartbleed"

# Test for outdated software
nikto -h target.com -Plugins "outdated"

Automation Scripts #

Batch Scanning Script #

bash
#!/bin/bash
# Batch web server scanning with Nikto

TARGETS_FILE="$1"
OUTPUT_DIR="nikto_scans_$(date +%Y%m%d_%H%M%S)"

if [ -z "$TARGETS_FILE" ]; then
    echo "Usage: $0 <targets_file>"
    echo "Example targets file format:"
    echo "http://target1.com"
    echo "https://target2.com:8443"
    echo "http://target3.com:8080"
    exit 1
fi

if [ ! -f "$TARGETS_FILE" ]; then
    echo "Error: Targets file not found: $TARGETS_FILE"
    exit 1
fi

mkdir -p "$OUTPUT_DIR"

echo "[+] Starting batch Nikto scan"
echo "[+] Targets file: $TARGETS_FILE"
echo "[+] Output directory: $OUTPUT_DIR"

# Function to scan a single target
scan_target() \\\\{
    local target="$1"
    local target_name=$(echo "$target"|sed 's|https\?://||'|sed 's|[:/]|_|g')
    local output_file="$OUTPUT_DIR/$\\\\{target_name\\\\}"

    echo "[+] Scanning: $target"

    # Run comprehensive scan
    nikto -h "$target" \
        -Tuning 1,2,3,4,5,7,8,9,a,b,c \
        -Format txt,xml,csv \
        -o "$output_file" \
        -timeout 10 \
        -maxtime 3600 \
        2>&1|tee "$\\\\{output_file\\\\}_console.log"

    if [ $? -eq 0 ]; then
        echo "  ✓ Scan completed: $target"
    else
        echo "  ✗ Scan failed: $target"
    fi
\\\\}

# Read targets and scan
while IFS= read -r target; do
    # Skip empty lines and comments
    [[ -z "$target"||"$target" =~ ^#.*$ ]] && continue

    scan_target "$target"

    # Wait between scans to be respectful
    sleep 5
done < "$TARGETS_FILE"

echo "[+] Batch scanning completed"
echo "[+] Results saved in: $OUTPUT_DIR"

# Generate summary report
echo "[+] Generating summary report..."

cat > "$OUTPUT_DIR/summary.html" << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>Nikto Scan Summary</title>
    <style>
        body \\\\{ font-family: Arial, sans-serif; margin: 20px; \\\\}
        table \\\\{ border-collapse: collapse; width: 100%; margin: 20px 0; \\\\}
        th, td \\\\{ border: 1px solid #ddd; padding: 8px; text-align: left; \\\\}
        th \\\\{ background-color: #f2f2f2; \\\\}
        .high \\\\{ color: #d32f2f; font-weight: bold; \\\\}
        .medium \\\\{ color: #f57c00; font-weight: bold; \\\\}
        .low \\\\{ color: #388e3c; \\\\}
        .info \\\\{ color: #1976d2; \\\\}
    </style>
</head>
<body>
    <h1>Nikto Scan Summary</h1>
    <p>Generated on: $(date)</p>
    <table>
        <tr><th>Target</th><th>Findings</th><th>Status</th></tr>
EOF

for log_file in "$OUTPUT_DIR"/*_console.log; do
    if [ -f "$log_file" ]; then
        target=$(basename "$log_file" _console.log)
        findings=$(grep -c "+" "$log_file" 2>/dev/null||echo "0")

        if [ "$findings" -gt 0 ]; then
            status="<span class='medium'>Issues Found</span>"
        else
            status="<span class='info'>Clean</span>"
        fi

        echo "        <tr><td>$target</td><td>$findings</td><td>$status</td></tr>" >> "$OUTPUT_DIR/summary.html"
    fi
done

cat >> "$OUTPUT_DIR/summary.html" << 'EOF'
    </table>
</body>
</html>
EOF

echo "[+] Summary report created: $OUTPUT_DIR/summary.html"

Continuous Monitoring Script #

bash
#!/bin/bash
# Continuous web application monitoring with Nikto

CONFIG_FILE="nikto_monitor.conf"
LOG_DIR="nikto_monitoring"
ALERT_EMAIL="security@company.com"

# Create default config if it doesn't exist
if [ ! -f "$CONFIG_FILE" ]; then
    cat > "$CONFIG_FILE" << 'EOF'
# Nikto monitoring configuration
# Format: URL|SCAN_INTERVAL|ALERT_THRESHOLD
https://app1.company.com|86400|5
https://app2.company.com|43200|3
http://internal.app.com:8080|21600|10
EOF
    echo "Created default config: $CONFIG_FILE"
    echo "Edit the configuration and run again"
    exit 1
fi

mkdir -p "$LOG_DIR"

# Function to send alert
send_alert() \\\\{
    local target="$1"
    local findings="$2"
    local threshold="$3"
    local report_file="$4"

    if [ "$findings" -gt "$threshold" ]; then
        echo "ALERT: $target has $findings findings (threshold: $threshold)"|\
            mail -s "Nikto Alert: $target" -A "$report_file" "$ALERT_EMAIL" 2>/dev/null||\
            echo "Alert: $target has $findings findings (email failed)"
    fi
\\\\}

# Function to scan target
monitor_target() \\\\{
    local target="$1"
    local threshold="$2"
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local target_name=$(echo "$target"|sed 's|https\?://||'|sed 's|[:/]|_|g')
    local report_file="$LOG_DIR/$\\\\{target_name\\\\}_$timestamp.txt"

    echo "[$(date)] Scanning $target"

    # Run Nikto scan
    nikto -h "$target" \
        -Tuning 1,2,3,4,5,7,8,9,a,b,c \
        -Format txt \
        -o "$report_file" \
        -timeout 10 \
        -maxtime 1800 \
        > /dev/null 2>&1

    if [ -f "$report_file" ]; then
        # Count findings
        findings=$(grep -c "+" "$report_file" 2>/dev/null||echo "0")

        echo "[$(date)] $target: $findings findings"

        # Send alert if threshold exceeded
        send_alert "$target" "$findings" "$threshold" "$report_file"

        # Keep only last 10 reports per target
        ls -t "$LOG_DIR/$\\\\{target_name\\\\}_"*.txt 2>/dev/null|tail -n +11|xargs rm -f 2>/dev/null

        return 0
    else
        echo "[$(date)] $target: Scan failed"
        return 1
    fi
\\\\}

# Main monitoring loop
echo "[$(date)] Starting Nikto monitoring"

while true; do
    while IFS='|' read -r target interval threshold; do
        # Skip comments and empty lines
        [[ "$target" =~ ^#.*$||-z "$target" ]] && continue

        # Check if it's time to scan this target
        target_name=$(echo "$target"|sed 's|https\?://||'|sed 's|[:/]|_|g')
        last_scan_file="$LOG_DIR/.$\\\\{target_name\\\\}_last_scan"

        current_time=$(date +%s)

        if [ -f "$last_scan_file" ]; then
            last_scan=$(cat "$last_scan_file")
            time_diff=$((current_time - last_scan))

            if [ "$time_diff" -lt "$interval" ]; then
                continue  # Not time to scan yet
            fi
        fi

        # Update last scan time
        echo "$current_time" > "$last_scan_file"

        # Run scan in background
        monitor_target "$target" "$threshold" &

    done < "$CONFIG_FILE"

    # Wait before next check
    sleep 300  # Check every 5 minutes
done

Vulnerability Correlation Script #

bash
#!/bin/bash
# Correlate Nikto findings with CVE references -> HTML report
# Usage: ./nikto_cve_correlate.sh <nikto_report.txt> [output.html]

NIKTO_REPORT="$1"
OUTPUT_FILE="${2:-nikto_cve_correlation.html}"
TMP_FINDINGS="$(mktemp)"
trap 'rm -f "$TMP_FINDINGS"' EXIT

if [ -z "$NIKTO_REPORT" ] || [ ! -f "$NIKTO_REPORT" ]; then
    echo "Usage: $0 <nikto_report.txt> [output.html]"
    exit 1
fi

echo "[+] Correlating Nikto findings with CVE references"

# Only real Nikto finding lines start with "+ "
grep '^+ ' "$NIKTO_REPORT" | while IFS= read -r line; do
    finding="${line#+ }"
    # One line, space-separated, deduplicated
    cve_refs=$(grep -oE 'CVE-[0-9]{4}-[0-9]{4,}' <<< "$finding" | sort -u | tr '\n' ' ')
    if [ -n "$cve_refs" ]; then
        echo "Finding: $finding"
        echo "CVE References: $cve_refs"
        echo "---"
    fi
done > "$TMP_FINDINGS"

FINDINGS_FILE="$TMP_FINDINGS" OUTPUT_FILE="$OUTPUT_FILE" python3 << 'EOF'
import os
import html
from datetime import datetime

findings_file = os.environ["FINDINGS_FILE"]
output_file = os.environ["OUTPUT_FILE"]

findings = []
current = {}
with open(findings_file, "r", encoding="utf-8", errors="replace") as f:
    for line in f:
        line = line.rstrip("\n")
        if line.startswith("Finding: "):
            if current:
                findings.append(current)
            current = {"finding": line[len("Finding: "):], "cves": []}
        elif line.startswith("CVE References: "):
            current["cves"] = line[len("CVE References: "):].split()
if current:
    findings.append(current)

parts = [f"""<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Nikto CVE Correlation Report</title>
<style>
  body {{ font-family: Arial, sans-serif; margin: 20px; }}
  .finding {{ margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }}
  .cve {{ margin: 5px 0; padding: 5px; background-color: #f5f5f5; }}
  .cve-link {{ color: #1976d2; text-decoration: none; }}
  .cve-link:hover {{ text-decoration: underline; }}
</style>
</head>
<body>
<h1>Nikto CVE Correlation Report</h1>
<p>Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<p>Total findings with CVE references: {len(findings)}</p>
"""]

for fd in findings:
    parts.append(f'<div class="finding">\n<h3>Finding</h3>\n'
                 f'<p>{html.escape(fd["finding"])}</p>\n<h4>CVE References</h4>\n')
    for cve in fd["cves"]:
        c = html.escape(cve)
        parts.append(
            f'<div class="cve"><strong>{c}</strong><br>'
            f'<a href="https://www.cve.org/CVERecord?id={c}" target="_blank" rel="noopener" class="cve-link">CVE.org</a> | '
            f'<a href="https://nvd.nist.gov/vuln/detail/{c}" target="_blank" rel="noopener" class="cve-link">NVD Details</a>'
            f'</div>\n')
    parts.append("</div>\n")

parts.append("</body>\n</html>\n")

with open(output_file, "w", encoding="utf-8") as f:
    f.write("".join(parts))

print(f"Found {len(findings)} findings with CVE references")
EOF

echo "[+] CVE correlation completed"
echo "[+] Report saved: $OUTPUT_FILE"

Integration Scripts #

Nmap + Nikto Integration #

bash
#!/bin/bash
# Discover web services with Nmap, then scan with Nikto

NETWORK="$1"
OUTPUT_DIR="nmap_nikto_$(date +%Y%m%d_%H%M%S)"

if [ -z "$NETWORK" ]; then
    echo "Usage: $0 <network>"
    echo "Example: $0 192.168.1.0/24"
    exit 1
fi

mkdir -p "$OUTPUT_DIR"

echo "[+] Discovering web services with Nmap"

# Discover web services
nmap -sS -p 80,443,8080,8443,8000,8888,9000,9090 \
    --open \
    -oG "$OUTPUT_DIR/nmap_web_services.gnmap" \
    "$NETWORK"

# Extract web services
grep -E "(80|443|8080|8443|8000|8888|9000|9090)/open" "$OUTPUT_DIR/nmap_web_services.gnmap"|\
    awk '\\\\{print $2\\\\}'|sort -u > "$OUTPUT_DIR/web_hosts.txt"

echo "[+] Found $(wc -l < "$OUTPUT_DIR/web_hosts.txt") hosts with web services"

# Scan each host with Nikto
while IFS= read -r host; do
    echo "[+] Scanning $host with Nikto"

    # Get open ports for this host
    ports=$(grep "$host" "$OUTPUT_DIR/nmap_web_services.gnmap"|\
            grep -oE '[0-9]+/open'|cut -d'/' -f1|tr '\n' ','|sed 's/,$//')

    if [ -n "$ports" ]; then
        nikto -h "$host" -p "$ports" \
            -Format txt,xml \
            -o "$OUTPUT_DIR/$\\\\{host\\\\}_nikto" \
            -timeout 10 \
            -maxtime 1800
    fi

    sleep 5  # Be respectful
done < "$OUTPUT_DIR/web_hosts.txt"

echo "[+] Nmap + Nikto scan completed"
echo "[+] Results saved in: $OUTPUT_DIR"

Burp Suite Integration #

bash
#!/bin/bash
# Push Nikto findings into Burp Suite's site map.
#   1. Parses the Nikto XML report (nikto -Format xml -o report.xml)
#   2. Writes a deduplicated list of finding URLs + a CSV summary
#   3. Optionally replays each URL through Burp's proxy so it appears
#      in Target > Site map, ready for Repeater / active scan.
#
# Usage: ./nikto_to_burp.sh <nikto_report.xml> [--replay] [proxy]
#   proxy defaults to http://127.0.0.1:8080

NIKTO_REPORT="$1"
REPLAY="$2"
BURP_PROXY="${3:-http://127.0.0.1:8080}"
URL_FILE="nikto_urls.txt"
CSV_FILE="nikto_findings.csv"

if [ -z "$NIKTO_REPORT" ] || [ ! -f "$NIKTO_REPORT" ]; then
    echo "Usage: $0 <nikto_report.xml> [--replay] [proxy_url]"
    exit 1
fi

echo "[+] Parsing Nikto XML report"

# Pass paths as real arguments: "python3 - args" makes sys.argv work
if ! python3 - "$NIKTO_REPORT" "$URL_FILE" "$CSV_FILE" << 'EOF'
import csv
import sys
import xml.etree.ElementTree as ET
from urllib.parse import urljoin

report, url_file, csv_file = sys.argv[1:4]

try:
    root = ET.parse(report).getroot()
except (ET.ParseError, OSError) as e:
    print(f"[-] Could not parse Nikto XML: {e}", file=sys.stderr)
    sys.exit(1)

def text(el, tag):
    child = el.find(tag)
    return (child.text or "").strip() if child is not None else ""

urls, rows = [], []
# Works for both <niktoscan> and multi-host <niktoscans> roots
for sd in root.iter("scandetails"):
    sitename = sd.get("sitename", "")          # e.g. https://host:443/
    for item in sd.iter("item"):
        uri = text(item, "uri") or "/"
        # namelink is Nikto's full URL; fall back to sitename + uri
        url = text(item, "namelink") or urljoin(sitename, uri)
        rows.append({
            "nikto_id": item.get("id", ""),
            "method": item.get("method", "GET"),
            "url": url,
            "description": text(item, "description"),
            "references": text(item, "references"),
        })
        if url not in urls:
            urls.append(url)

if not rows:
    print("[-] No <scandetails>/<item> elements found - is this a Nikto -Format xml report?",
          file=sys.stderr)
    sys.exit(1)

with open(url_file, "w") as f:
    f.write("\n".join(urls) + "\n")

with open(csv_file, "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=rows[0].keys())
    w.writeheader()
    w.writerows(rows)

print(f"[+] {len(rows)} findings, {len(urls)} unique URLs")
EOF
then
    echo "[-] Conversion failed"
    exit 1
fi

echo "[+] URL list: $URL_FILE"
echo "[+] Findings summary: $CSV_FILE"

if [ "$REPLAY" = "--replay" ]; then
    echo "[+] Replaying URLs through Burp proxy at $BURP_PROXY"
    while IFS= read -r url; do
        [ -z "$url" ] && continue
        code=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 15 \
               --proxy "$BURP_PROXY" "$url")
        echo "    [$code] $url"
    done < "$URL_FILE"
    echo "[+] Done - check Target > Site map in Burp"
fi

Troubleshooting #

Common Issues #

SSL/TLS Problems #

bash
# Test SSL connectivity
openssl s_client -connect target.com:443

# Force SSL version
nikto -h https://target.com -ssl -sslversion 3

# Ignore SSL certificate errors
nikto -h https://target.com -ssl -nossl

# Debug SSL issues
nikto -h https://target.com -ssl -Display E

Timeout Issues #

bash
# Increase timeout
nikto -h target.com -timeout 30

# Set maximum scan time
nikto -h target.com -maxtime 7200

# Reduce scan scope
nikto -h target.com -Tuning 1,2,3

# Use fewer plugins
nikto -h target.com -Plugins "headers,robots"

Performance Issues #

bash
# Reduce scan intensity
nikto -h target.com -Pause 5

# Limit concurrent connections
nikto -h target.com -timeout 10 -maxtime 3600

# Use specific tuning to reduce load
nikto -h target.com -Tuning x6  # Exclude DoS tests

# Scan specific directories only
nikto -h target.com -root /app/

Database Updates #

bash
# Update Nikto database
nikto -update

# Check database version
nikto -Version

# Manual database update
cd /var/lib/nikto
wget https://cirt.net/nikto/UPDATES/2.1.6/db_tests

Debugging and Logging #

bash
# Enable debug output
nikto -h target.com -Display E

# Verbose output
nikto -h target.com -verbose

# Save debug information
nikto -h target.com -Display E -o debug.log

# Check configuration
nikto -config