mcpField
P
port-service-discovery

port-service-discovery

github.com/uphiagoSecurity1.3k40 installsUpdated 8w ago
Repository

About port-service-discovery

A security assessment skill for scoped Nmap discovery of services adjacent to web applications. It guides operators through port scanning, service verification, exposure checks, and recording findings.

Key features

  1. 01Scoped Nmap port scans
  2. 02Service version detection
  3. 03Checks for critical exposures
  4. 04Firewall and WAF fingerprinting
  5. 05Finding verification guidance

Use cases

  1. 01Inspect infrastructure after web reconnaissance
  2. 02Check backend ports on staging hosts
  3. 03Validate exposed database or admin services

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/uphiago/recon-skills --skill port-service-discovery

After installing, type/port-service-discoveryin Claude Code to confirm it loaded.

Details

From the project README

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-invade Phase 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

  • nmap available 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 TARGET

Quick Reference

PortServiceFinding Severity
3306MySQLCritical (if open to internet)
27017MongoDBCritical (if no auth)
6379RedisCritical (if no auth)
5432PostgreSQLHigh
1433MS SQL ServerHigh
21FTPHigh (anonymous login?)
22SSHInfo (check for weak auth)
8080/8081/8082/8084Internal APIsHigh (backend services exposed)
9200ElasticsearchHigh (data exposure)
25/587SMTPMedium (open relay?)
110/143/993POP3/IMAPInfo
8443HTTPS alt (admin panels)Medium
9090Prometheus/CockpitMedium
3000Grafana/Node.js devMedium

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"
fi
Step 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"
fi
Step 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
fi
Step 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 1 on 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 curl with 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 PONG to PING command.
  • FTP anonymous MUST return code 230 (login successful).
  • All findings MUST be documented with exact port, service, version, and access level.

Comments

Markdown supported