How to Find Subdomains Using Shodan and the Favicon Hash Trick
Press enter or click to view image in full sizeFind Subdomains Using Shodan and the Favicon Hash Tri 2026-5-14 11:32:0 Author: infosecwriteups.com(查看原文) 阅读量:29 收藏

MD Mehedi Hasan

Press enter or click to view image in full size

Find Subdomains Using Shodan and the Favicon Hash Trick

Subdomain enumeration is the foundation of any serious bug bounty reconnaissance. While tools like Sublist3r, Amass, and crt.sh are excellent, they rely on DNS records and certificate transparency logs — which means they only find what’s publicly indexed.

There’s a smarter way.

Many organizations reuse the same favicon across their entire infrastructure — main site, subdomains, staging servers, CDN nodes, and even internal tools. This means the favicon acts as a unique fingerprint. If you can hash it and search Shodan’s indexed data, you can discover subdomains and servers that no DNS brute-force tool will ever find.

Get MD Mehedi Hasan’s stories in your inbox

Join Medium for free to get updates from this writer.

Remember me for faster sign in

This guide walks you through the entire process on Kali Linux, from calculating the favicon hash to extracting live, validated subdomains.

How It Works

Target Domain (example.com)


Download Favicon → Compute MurmurHash3 → Search Shodan


Shodan returns all IPs/hostnames sharing that favicon hash


Extract hostnames → DNS resolution → HTTP validation


Live Subdomains Discovered

The key insight: Shodan indexes favicon hashes for every website it scans. The search filter http.favicon.hash:<hash> lets you query all servers worldwide that share the exact same favicon as your target.

Prerequisites

Press enter or click to view image in full size

Prerequisites

Install Required Tools

# Install dnsx and httpx (ProjectDiscovery tools)
go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest
go install github.com/projectdiscovery/httpx/cmd/httpx@latest
sudo cp ~/go/bin/dnsx /usr/bin/
sudo cp ~/go/bin/httpx /usr/bin/

Step 1: Install Shodan CLI

Install via pip

pip3 install shodan

Verify Installation

shodan --help

Initialize with Your API Key

You need a Shodan API key. Get yours at: https://account.shodan.io

shodan init YOUR_SHODAN_API_KEY

Replace YOUR_SHODAN_API_KEY with your actual key.

Test Your Connection

shodan info

Expected output:

Query credits available: 100
Scan credits available: 0

Step 2: Extract the Favicon & Calculate Its Hash

Method A: Favicon at Standard Location

Most sites host their favicon at /favicon.ico. Download it with:

curl -s https://example.com/favicon.ico -o favicon.ico

Method B: Favicon at Custom Location

If the standard location doesn’t work, inspect the HTML source:

curl -s https://example.com | grep -i "favicon\|icon" | grep -oP 'href="\K[^"]+'

Then download from the discovered path:

curl -s https://example.com/path/to/favicon.ico -o favicon.ico

Calculate the Favicon Hash

Create a Python script called favicon_hash.py:

#!/usr/bin/env python3
"""
Favicon Hash Calculator for Shodan Reconnaissance
Usage: python3 favicon_hash.py <favicon_url>
"""
import mmh3
import requests
import sys
import codecs
def calculate_favicon_hash(url):
"""Download favicon and calculate MurmurHash3 hash."""
try:
response = requests.get(url, timeout=10, verify=False)
response.raise_for_status()

favicon = response.content
hash_value = mmh3.hash(favicon)

print(f"[+] URL: {url}")
print(f"[+] Favicon Hash: {hash_value}")
print(f"[+] Use in Shodan: http.favicon.hash:{hash_value}")

return hash_value

except requests.exceptions.RequestException as e:
print(f"[-] Error downloading favicon: {e}")
sys.exit(1)
except Exception as e:
print(f"[-] Error calculating hash: {e}")
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 favicon_hash.py <favicon_url>")
print("Example: python3 favicon_hash.py https://example.com/favicon.ico")
sys.exit(1)

# Suppress SSL warnings for self-signed certs
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

calculate_favicon_hash(sys.argv[1])

Make it executable:

chmod +x favicon_hash.py

Install the required library:

pip3 install mmh3 requests

Run the Script

python3 favicon_hash.py https://example.com/favicon.ico

Example Output:

[+] URL: https://example.com/favicon.ico
[+] Favicon Hash: 123456789
[+] Use in Shodan: http.favicon.hash:123456789

One-Liner Alternative (No Script File)

If you prefer not to create a file, use this one-liner:

python3 -c "import mmh3, requests; print(f'Favicon Hash: {mmh3.hash(requests.get(\"https://example.com/favicon.ico\").content)}')"

Step 3: Search Shodan for Matching Favicon Hash

Now the real magic begins. Use the hash to find every server Shodan has indexed that shares the same favicon.

Basic Search

shodan search --fields ip_str,port,hostnames "http.favicon.hash:123456789" > shodan_results.txt

With Additional Filters

Refine your search to focus on specific ports or countries:

# HTTPS only
shodan search --fields ip_str,port,hostnames "http.favicon.hash:123456789 port:443" > shodan_https.txt

# Specific country (e.g., United States)
shodan search --fields ip_str,port,hostnames "http.favicon.hash:123456789 country:US" > shodan_us.txt

# Specific organization
shodan search --fields ip_str,port,hostnames "http.favicon.hash:123456789 org:\"Target Inc\"" > shodan_org.txt

Download Large Result Sets

For targets with many results, use Shodan’s download feature:

shodan download --limit 5000 search_results "http.favicon.hash:123456789"
shodan parse --fields ip_str,port,hostnames search_results.json.gz > shodan_results.txt

Step 4: Parse and Extract Subdomains

View Raw Results

cat shodan_results.txt

Example Output:

93.184.216.34    80    www.example.com
93.184.216.35 443 sub1.example.com
93.184.216.36 80 sub2.example.com
192.168.1.10 8080 staging.example.com
10.0.0.5 443 admin.internal.example.com

Extract Hostnames Only

awk '{print $3}' shodan_results.txt | sort -u > subdomains.txt

View Extracted Subdomains

cat subdomains.txt

Expected Output:

www.example.com
sub1.example.com
sub2.example.com
staging.example.com
admin.internal.example.com

Alternative: Extract Hostnames with IPs

For later reference, keep the IP-to-hostname mapping:

awk '{print $1 "\t" $3}' shodan_results.txt | sort -u > ip_hostname_map.txt

Step 5: Validate and Filter Live Subdomains

Not all extracted hostnames will resolve. We need to validate them.

DNS Resolution with dnsx

cat subdomains.txt | dnsx -silent -o resolved_subdomains.txt

Check for Live HTTP/HTTPS with httpx

cat resolved_subdomains.txt | httpx -silent -o live_subdomains.txt

Full Validation Pipeline (One Command)

bash

cat subdomains.txt | dnsx -silent | httpx -silent -o live_subdomains.txt

View Live Subdomains

bash

cat live_subdomains.txt

Expected Output:

https://www.example.com
https://sub1.example.com
https://sub2.example.com
https://staging.example.com

Enrich with Status Codes and Titles

cat resolved_subdomains.txt | httpx -silent -status-code -title -o enriched.txt
cat enriched.txt

Example Output:

https://www.example.com [200] [Example Domain]
https://sub1.example.com [200] [Dashboard - Login]
https://staging.example.com [302] [Redirecting...]
https://admin.internal.example.com [403] [Forbidden]

Complete One-Click Automation Script

Create favicon_subdomain_scanner.sh:

#!/bin/bash

# Favicon-Based Subdomain Discovery Tool
# Author: SecurityTalent
# Usage: ./favicon_subdomain_scanner.sh <domain>
set -e
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
if [ $# -lt 1 ]; then
echo -e "${RED}Usage: $0 <domain> [favicon_url]${NC}"
echo -e "${YELLOW}Example: $0 example.com${NC}"
echo -e "${YELLOW}Example: $0 example.com https://example.com/custom/favicon.ico${NC}"
exit 1
fi
DOMAIN=$1
FAVICON_URL=${2:-"https://$DOMAIN/favicon.ico"}
OUTPUT_DIR="favicon_recon_$DOMAIN"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
echo -e "${GREEN}[+] Target Domain: $DOMAIN${NC}"
echo -e "${GREEN}[+] Favicon URL: $FAVICON_URL${NC}"
echo -e "${GREEN}[+] Output Directory: $OUTPUT_DIR${NC}"
echo ""
mkdir -p "$OUTPUT_DIR"
# Step 1: Download favicon and calculate hash
echo -e "${YELLOW}[*] Step 1: Downloading favicon and calculating hash...${NC}"
curl -s "$FAVICON_URL" -o "$OUTPUT_DIR/favicon.ico"
if [ ! -f "$OUTPUT_DIR/favicon.ico" ] || [ ! -s "$OUTPUT_DIR/favicon.ico" ]; then
echo -e "${RED}[-] Failed to download favicon. Trying alternative discovery...${NC}"
# Try to find favicon from HTML
FAV_ALT=$(curl -s "https://$DOMAIN" | grep -oP 'href="\K[^"]*favicon[^"]*' | head -1)
if [ -n "$FAV_ALT" ]; then
if [[ "$FAV_ALT" == http* ]]; then
FAVICON_URL="$FAV_ALT"
else
FAVICON_URL="https://$DOMAIN$FAV_ALT"
fi
echo -e "${GREEN}[+] Discovered alternative favicon URL: $FAVICON_URL${NC}"
curl -s "$FAVICON_URL" -o "$OUTPUT_DIR/favicon.ico"
else
echo -e "${RED}[-] Could not find favicon. Exiting.${NC}"
exit 1
fi
fi
HASH=$(python3 -c "import mmh3; print(mmh3.hash(open('$OUTPUT_DIR/favicon.ico','rb').read()))")
echo -e "${GREEN}[+] Favicon Hash: $HASH${NC}"
echo "$HASH" > "$OUTPUT_DIR/favicon_hash.txt"
# Step 2: Search Shodan
echo -e "${YELLOW}[*] Step 2: Searching Shodan for matching favicon hash...${NC}"
shodan search --fields ip_str,port,hostnames "http.favicon.hash:$HASH" > "$OUTPUT_DIR/shodan_raw.txt"
echo -e "${GREEN}[+] Shodan results saved to $OUTPUT_DIR/shodan_raw.txt${NC}"
# Step 3: Extract hostnames
echo -e "${YELLOW}[*] Step 3: Extracting hostnames...${NC}"
awk '{print $3}' "$OUTPUT_DIR/shodan_raw.txt" | grep -v "^$" | sort -u > "$OUTPUT_DIR/subdomains_raw.txt"
echo -e "${GREEN}[+] $(wc -l < "$OUTPUT_DIR/subdomains_raw.txt") unique hostnames found${NC}"
# Step 4: DNS Resolution
echo -e "${YELLOW}[*] Step 4: Resolving DNS...${NC}"
cat "$OUTPUT_DIR/subdomains_raw.txt" | dnsx -silent -o "$OUTPUT_DIR/resolved.txt" 2>/dev/null || \
cat "$OUTPUT_DIR/subdomains_raw.txt" > "$OUTPUT_DIR/resolved.txt"
echo -e "${GREEN}[+] $(wc -l < "$OUTPUT_DIR/resolved.txt") resolved hostnames${NC}"
# Step 5: HTTP Validation
echo -e "${YELLOW}[*] Step 5: Checking live HTTP hosts...${NC}"
cat "$OUTPUT_DIR/resolved.txt" | httpx -silent -status-code -title -o "$OUTPUT_DIR/live_enriched.txt" 2>/dev/null || \
cat "$OUTPUT_DIR/resolved.txt" > "$OUTPUT_DIR/live_enriched.txt"
# Extract just URLs
awk '{print $1}' "$OUTPUT_DIR/live_enriched.txt" > "$OUTPUT_DIR/live_subdomains.txt"
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} RECONNAISSANCE COMPLETE${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}[+] Target: $DOMAIN${NC}"
echo -e "${GREEN}[+] Favicon Hash: $HASH${NC}"
echo -e "${GREEN}[+] Total Subdomains Found: $(wc -l < "$OUTPUT_DIR/subdomains_raw.txt")${NC}"
echo -e "${GREEN}[+] Live Subdomains: $(wc -l < "$OUTPUT_DIR/live_subdomains.txt")${NC}"
echo ""
echo -e "${YELLOW}Results saved to: $OUTPUT_DIR/${NC}"
echo -e "${YELLOW} - favicon_hash.txt${NC}"
echo -e "${YELLOW} - shodan_raw.txt${NC}"
echo -e "${YELLOW} - subdomains_raw.txt${NC}"
echo -e "${YELLOW} - resolved.txt${NC}"
echo -e "${YELLOW} - live_subdomains.txt${NC}"
echo -e "${YELLOW} - live_enriched.txt${NC}"
echo ""
echo -e "${GREEN}Live Subdomains:${NC}"
cat "$OUTPUT_DIR/live_subdomains.txt"

Make it executable and run:

chmod +x favicon_subdomain_scanner.sh

# Basic usage
./favicon_subdomain_scanner.sh example.com
# With custom favicon URL
./favicon_subdomain_scanner.sh example.com https://example.com/assets/custom-icon.ico

Tips for Bug Bounty Hunters

1. Cross-Check Technologies

Use WhatWeb or Wappalyzer to verify if discovered subdomains share the same tech stack:

whatweb -l subdomains_raw.txt

2. Expand the Attack Surface

Once you have live subdomains, test for:

# Directory fuzzing
ffuf -u https://subdomain.com/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

# Open ports
nmap -sC -sV -p- subdomain.com
# .git exposure
gau subdomain.com | grep "\.git"
# CORS misconfigurations
corsy -u https://subdomain.com

3. Known Favicon Hashes for Quick Wins

Press enter or click to view image in full size

Known Favicon Hashes for Quick Wins
# Quick search for all WordPress sites (hash: 116323821)
shodan search --fields ip_str,port,hostnames "http.favicon.hash:116323821"

4. Automate with Shodan API

For large-scale searches with full result sets:

# Download up to 10,000 results
shodan download --limit 10000 search_results "http.favicon.hash:123456789"

# Parse the compressed results
shodan parse --fields ip_str,port,hostnames search_results.json.gz > full_results.txt

5. Combine with Other Tools

# Merge with traditional subdomain enumeration
subfinder -d example.com -o subfinder_domains.txt
cat subfinder_domains.txt subdomains_raw.txt | sort -u > all_subdomains.txt

# Check with crt.sh
curl -s "https://crt.sh/?q=%25.example.com&output=json" | jq -r '.[].name_value' | sort -u >> all_subdomains.txt
# Validate all combined
cat all_subdomains.txt | httpx -silent -o final_live.txt

6. Common Favicon Locations to Check

# Standard locations many targets use
for path in /favicon.ico /favicon.png /assets/favicon.ico /static/favicon.ico /images/favicon.ico /img/favicon.ico; do
echo "Checking: https://example.com$path"
curl -s -o /dev/null -w "%{http_code}" "https://example.com$path"
echo ""
done

7. Handle Redirects

Some favicons are served via redirect. Follow them:

curl -sL https://example.com/favicon.ico -o favicon.ico

Why This Works

Technical Explanation

The favicon hash technique works because of three key factors:

  1. Favicon Reuse — Organizations consistently reuse their favicon across all subdomains, staging environments, CDN endpoints, and even internal applications. It’s a branding artifact that gets copied everywhere.
  2. Shodan Indexing — Shodan continuously scans the internet and indexes http.favicon.hash as a searchable field for every HTTP response that contains a favicon.
  3. MurmurHash3 Consistency — The hash algorithm produces the same output for the same binary input. Any server serving the exact same favicon file will produce the identical hash, regardless of the domain name or IP address.

What You Can Discover That Other Tools Miss

Discover Other Tools

Troubleshooting

Issue 1: Shodan Returns No Results

# Check if you have credits
shodan info

# Test with a known hash (Google's favicon)
shodan search --fields ip_str,port,hostnames "http.favicon.hash:-305179312"

Issue 2: Favicon Download Fails

# Test with verbose curl
curl -v https://example.com/favicon.ico

# Try without SSL verification
curl -sk https://example.com/favicon.ico -o favicon.ico

Issue 3: “mmh3” Module Not Found

pip3 install mmh3
# If that fails, try:
pip3 install mmh3cffi

Issue 4: “shodan: command not found”

# Find where pip installed it
python3 -m shodan --help

# Add to PATH
export PATH=$PATH:~/.local/bin
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc

Issue 5: HTTPX/DNSX Not Found

# Install from Go
go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest
go install github.com/projectdiscovery/httpx/cmd/httpx@latest

# Copy to PATH
sudo cp ~/go/bin/dnsx /usr/local/bin/
sudo cp ~/go/bin/httpx /usr/local/bin/

Ethical & Legal Reminder

IMPORTANT: This technique discovers servers and subdomains that may include staging, internal, or development environments. Only test targets you are explicitly authorized to assess.

  • Bug Bounty: Verify scope before testing any discovered subdomain
  • Pentesting: Include all discovered assets in your Rules of Engagement
  • Disclosure: Report discovered internal/development servers responsibly

Conclusion

The favicon hash trick is one of the most underutilized techniques in bug bounty reconnaissance. While everyone else is brute-forcing DNS records and scraping certificate logs, you can leverage Shodan’s massive indexed dataset to find hidden assets based on a single shared favicon.

Key Takeaways

Press enter or click to view image in full size

Key Takeaways

Quick Reference (One-Click)

# Complete workflow in 3 commands
HASH=$(python3 -c "import mmh3, requests; print(mmh3.hash(requests.get('https://example.com/favicon.ico').content))")
shodan search --fields ip_str,port,hostnames "http.favicon.hash:$HASH" | awk '{print $3}' | sort -u | dnsx -silent | httpx -silent -status-code -title

What’s Next?

Once you have your live subdomains, consider:

  • Port scanning with naabu or nmap
  • Directory fuzzing with ffuf or gobuster
  • Technology fingerprinting with wappalyzer or whatweb
  • JavaScript analysis with subjs or jsluice
  • Endpoint discovery with gau or katana

Complete Setup Script

Save as setup_favicon_recon.sh:

#!/bin/bash

echo "[+] Installing required Python packages..."
pip3 install shodan mmh3 requests --quiet
echo "[+] Installing Go tools..."
go install github.com/projectdiscovery/dnsx/cmd/dnsx@latest
go install github.com/projectdiscovery/httpx/cmd/httpx@latest
sudo cp ~/go/bin/dnsx /usr/bin/
sudo cp ~/go/bin/httpx /usr/bin/
echo "[+] Creating favicon_hash.py..."
cat > favicon_hash.py << 'PYEOF'
#!/usr/bin/env python3
import mmh3, requests, sys, urllib3
urllib3.disable_warnings()
if len(sys.argv) != 2:
print("Usage: python3 favicon_hash.py <url>")
sys.exit(1)
r = requests.get(sys.argv[1], timeout=10, verify=False)
print(f"Favicon Hash: {mmh3.hash(r.content)}")
PYEOF
chmod +x favicon_hash.py
echo ""
echo "[+] Setup Complete!"
echo ""
echo "[+] Test with: python3 favicon_hash.py https://example.com/favicon.ico"
echo "[+] Then: shodan search --fields ip_str,port,hostnames \"http.favicon.hash:<HASH>\""


文章来源: https://infosecwriteups.com/how-to-find-subdomains-using-shodan-and-the-favicon-hash-trick-ac01741b0fb5?source=rss----7b722bfd1b8d---4
如有侵权请联系:admin#unsafe.sh