port-service-discovery – Security skill for AI agents
Nmap scan for MySQL, Redis, FTP, SSH, internal API services.
Install the port-service-discovery skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/port-service-discovery-4a64f.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /port-service-discovery – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/port-service-discovery-4a64f.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $port-service-discovery – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/port-service-discovery-4a64f.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /port-service-discovery – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/port-service-discovery-4a64f.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /port-service-discovery – then describe the task you want done.
SKILL.md content
Port & Service Discovery Skill
Use scoped Nmap discovery to identify services adjacent to web applications,
including databases, remote administration, mail, caches, and non-standard API
ports. An open port is an observation; service identity and unauthorized access
require separate validation.
When to Use
- Running
deep-invadePhase 6 on a high-value target. - After surface recon shows no exploitable web vulnerabilities — pivot to infrastructure.
- When the target is a SaaS with backend APIs on non-standard ports.
- After discovering a staging subdomain — check for database/admin ports.
Prerequisites
nmapavailable in the execution environment.- Target domain or IP address.
- For full port scan: patience (can take 10-60 minutes for all 65535 ports).
How to Run
# Fast top-100 port scan (30 seconds)
nmap -F --open -T4 TARGET -oN nmap_fast.txt
# Top 1000 ports (2-3 minutes)
nmap --top-ports 1000 --open -T4 TARGET -oN nmap_1000.txt
# Service version detection on open ports
nmap -sV -p $(grep 'open' nmap_fast.txt | cut -d/ -f1 | tr '\n' ',') TARGET
# Firewall bypass: fragment packets
nmap -f -F TARGETQuick Reference
| Port | Service | Finding Severity |
|------|---------|-----------------|
| 3306 | MySQL | Critical (if open to internet) |
| 27017 | MongoDB | Critical (if no auth) |
| 6379 | Redis | Critical (if no auth) |
| 5432 | PostgreSQL | High |
| 1433 | MS SQL Server | High |
| 21 | FTP | High (anonymous login?) |
| 22 | SSH | Info (check for weak auth) |
| 8080/8081/8082/8084 | Internal APIs | High (backend services exposed) |
| 9200 | Elasticsearch | High (data exposure) |
| 25/587 | SMTP | Medium (open relay?) |
| 110/143/993 | POP3/IMAP | Info |
| 8443 | HTTPS alt (admin panels) | Medium |
| 9090 | Prometheus/Cockpit | Medium |
| 3000 | Grafana/Node.js dev | Medium |
Procedure
Step 1 — Fast Top-100 Scan
TARGET="$1"
OUTDIR="$OUTDIR/ports"
mkdir -p "$OUTDIR"
echo "[*] Fast scan (top 100 ports) on $TARGET..."
nmap -F --open -T4 --max-retries 1 --host-timeout 60s "$TARGET" -oN "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null
echo "[*] Open ports:"
grep 'open' "$OUTDIR/${TARGET}_fast.nmap" || echo " None found"Step 2 — Service Version Detection
TARGET="$1"
OUTDIR="$OUTDIR/ports"
# Get comma-separated list of open ports
OPEN_PORTS=$(grep '^[0-9]' "$OUTDIR/${TARGET}_fast.nmap" | awk -F/ '{print $1}' | tr '\n' ',' | sed 's/,$//')
if [[ -n "$OPEN_PORTS" ]]; then
echo "[*] Service detection on ports: $OPEN_PORTS"
nmap -sV --version-intensity 5 -p "$OPEN_PORTS" "$TARGET" -oN "$OUTDIR/${TARGET}_services.nmap" 2>/dev/null
echo "[*] Services:"
grep 'open' "$OUTDIR/${TARGET}_services.nmap"
else
echo "[-] No open ports found"
fiStep 3 — Critical Exposure Check
TARGET="$1"
OUTDIR="$OUTDIR/ports"
echo "[*] Critical exposure assessment:"
# MySQL (3306)
if grep -q '3306.*open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[CRITICAL] MySQL 3306 OPEN — attempting banner grab..."
# Try to get MySQL version
mysql_info=$(timeout 5 nc -w 3 "$TARGET" 3306 </dev/null 2>/dev/null | head -1)
[[ -n "$mysql_info" ]] && echo " Banner: $mysql_info"
# Test for no-auth MySQL
echo " Testing anonymous access..."
# This typically requires mysql client; note methodology
echo " Manual check: mysql -h $TARGET -u root --skip-ssl"
echo " Manual check: mysql -h $TARGET -u admin --skip-ssl"
fi
# MongoDB (27017)
if grep -q '27017.*open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[CRITICAL] MongoDB 27017 OPEN"
echo " Manual check: mongosh mongodb://$TARGET:27017"
fi
# Redis (6379)
if grep -q '6379.*open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[HIGH] Redis 6379 OPEN — testing no-auth access..."
redis_test=$(timeout 5 bash -c "echo -e 'PING\r\nINFO\r\n' | nc -w 3 '$TARGET' 6379 2>/dev/null")
if echo "$redis_test" | grep -q "PONG"; then
echo " [CRITICAL] Redis NO AUTH — full access!"
echo " Response: $(echo "$redis_test" | head -5)"
else
echo " Redis requires auth (or connection failed)"
fi
fi
# Internal API ports (8080-8089)
for port in 8080 8081 8082 8084 8088 8443 3000 5000 9000 9090; do
if grep -q "${port}.*open" "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[HIGH] Port $port OPEN — probing HTTP..."
http_code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 5 "http://$TARGET:$port/" 2>/dev/null)
if [[ "$http_code" != "000" ]]; then
echo " HTTP $http_code on port $port"
title=$(curl -sk --max-time 5 --connect-timeout 5 "http://$TARGET:$port/" 2>/dev/null | grep -Eo '<title>\K[^<]+')
[[ -n "$title" ]] && echo " Title: $title"
# Check for Swagger/API docs
for api_path in "swagger.json" "api-docs" "swagger-ui.html" "graphql" "actuator/health"; do
api_code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 --connect-timeout 5 "http://$TARGET:$port/$api_path")
[[ "$api_code" == "200" ]] && echo " [API] http://$TARGET:$port/$api_path (HTTP 200)"
sleep 0.2
done
fi
fi
done
# FTP (21) — check for anonymous login
if grep -q '21.*open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[HIGH] FTP 21 OPEN — testing anonymous login..."
anon_test=$(timeout 10 bash -c "echo -e 'anonymous\nanonymous\n' | nc -w 3 '$TARGET' 21 2>/dev/null")
if echo "$anon_test" | grep -qi "230"; then
echo " [CRITICAL] Anonymous FTP login successful!"
elif echo "$anon_test" | grep -qi "530\|331"; then
echo " Anonymous FTP: requires auth"
fi
fi
# SSH (22) — check for weak ciphers
if grep -q '22.*open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo ""
echo "[INFO] SSH 22 OPEN"
ssh_banner=$(timeout 5 nc -w 3 "$TARGET" 22 </dev/null 2>/dev/null | head -1)
[[ -n "$ssh_banner" ]] && echo " Banner: $ssh_banner"
fiStep 4 — Extended Port Range (when fast scan finds nothing)
TARGET="$1"
OUTDIR="$OUTDIR/ports"
# If no ports found in top-100, expand to top-1000
if ! grep -q 'open' "$OUTDIR/${TARGET}_fast.nmap" 2>/dev/null; then
echo "[*] No ports in top-100, scanning top-1000..."
nmap --top-ports 1000 --open -T4 --max-retries 1 --host-timeout 120s "$TARGET" -oN "$OUTDIR/${TARGET}_1000.nmap" 2>/dev/null
OPEN=$(grep 'open' "$OUTDIR/${TARGET}_1000.nmap")
if [[ -z "$OPEN" ]]; then
# Try SYN scan with fragmentation for firewall evasion
echo "[*] Still nothing — trying fragmented SYN scan..."
nmap -f -sS -F --open -T4 "$TARGET" -oN "$OUTDIR/${TARGET}_frag.nmap" 2>/dev/null
fi
fiStep 5 — Firewall/WAF Fingerprinting
TARGET="$1"
echo "[*] WAF/CDN detection:"
# Check for Cloudflare
cf_header=$(curl -skI --max-time 5 --connect-timeout 5 "https://$TARGET/" 2>/dev/null | grep -i "cf-ray\|cloudflare")
[[ -n "$cf_header" ]] && echo " Cloudflare detected"
# Check for AWS CloudFront
cf_header=$(curl -skI --max-time 5 --connect-timeout 5 "https://$TARGET/" 2>/dev/null | grep -i "x-amz-cf\|cloudfront")
[[ -n "$cf_header" ]] && echo " AWS CloudFront detected"
# Check origin IP (bypass CDN)
echo "[*] Historical DNS records for origin IP discovery:"
# SecurityTrails, DNSDumpster, etc. — use HTTP fetch for these
echo " Manual: securitytrails.com/domain/$TARGET/dns/a"
echo " Manual: dnsdumpster.com"
# Try direct IP connection (if known)
# curl -sk --resolve "$TARGET:443:ORIGIN_IP" "https://$TARGET/"Pitfalls
- nmap SYN scan requires raw-socket privileges. Use
-sT(TCP connect)
when the execution environment does not grant them.
- Rate limiting on port scans. Some providers (AWS, Cloudflare) rate-limit or block port scans. Use
-T2(polite timing) and--max-retries 1on sensitive targets. - MySQL/MongoDB banner grab may not work. Some DBs require TLS negotiation (MySQL 8.0+ defaults to
caching_sha2_password). Banner may be empty. - Internal API ports may time out. Some services only respond to specific Host headers or valid HTTP requests. Use
curlwith various Host headers.
Verification
- Every open port MUST be confirmed with service version detection (
nmap -sV). - MySQL access MUST be tested with actual connection attempt (not just port open).
- Redis no-auth MUST return
PONGtoPINGcommand. - FTP anonymous MUST return code 230 (login successful).
- All findings MUST be documented with exact port, service, version, and access level.
Related skills
- recon-playbook – Use when starting or restructuring an authorized external web and API assessment.
- recon-sector – Parameterized sector recon using sector database.
- recon-sector-expansion – Multi-sector batch domain expansion — identify untested/under-tested sectors, generate…
- container-scanning – Scan container images for vulnerabilities using Trivy, Grype, and cloud-native tools.
- container-security-hardening – Harden Docker/container images and runtime deployments with secure base images, non-root…
- s3-minio-content-type-xss – Exploit public bucket Content-Type override for stored XSS on target origin.
- qutip – Simulate and audit closed and open quantum-system models with QuTiP 5, including…
- sast-configuration – Configure Static Application Security Testing (SAST) tools for automated vulnerability…