Aller au contenu principal

OSINT — Démonstration guidée

Une cible. Une vraie. On ne va rien lui envoyer. Et à la fin, on saura : ses sous-domaines, ses technologies, ses employés clés, ses fuites, et ses cinq points faibles probables.

Le choix de la cible pour cette démo

On utilise un programme de bug bounty public, où l'entreprise autorise explicitement les tests dans un cadre défini. Vous pouvez faire pareil chez vous en choisissant un programme sur HackerOne ou Bugcrowd. Dans la démo qui suit, on utilise un nom fictif demo-corp.com pour illustrer — mais tout ce que vous voyez est reproductible sur une cible réelle autorisée.

Ce que vous saurez faire après cette leçon

  • Passer d'un simple nom de domaine à une carte d'infrastructure en 90 minutes.
  • Utiliser crt.sh, subfinder, amass -passive, dnsx (mode passif), theHarvester, whatweb.
  • Distinguer les sous-domaines vivants des sous-domaines morts sans les toucher.
  • Recouper trois sources indépendantes avant de conclure.
  • Produire une fiche cible de 2 pages exploitable dès le module 4.

Étape 0 — Le point de départ

Une simple ligne :

Cible : demo-corp.com
Programme : bug bounty public, scope in-scope = *.demo-corp.com

C'est tout. On part de là.

Créez le dossier de travail :

mkdir -p ~/osint/demo-corp/{dns,subs,tech,people,leaks,archive}
cd ~/osint/demo-corp

Chaque famille de source aura son sous-dossier. Discipline dès le départ.


Étape 1 — DNS de base (2 minutes)

Les enregistrements essentiels, un par un :

for t in A AAAA MX NS TXT SOA CAA; do
echo "=== $t ==="
dig +short demo-corp.com $t
done | tee dns/racine.txt

Sortie typique :

=== A ===
104.21.44.15
172.67.187.219
=== AAAA ===
=== MX ===
1 aspmx.l.google.com.
5 alt1.aspmx.l.google.com.
=== NS ===
ada.ns.cloudflare.com.
kirk.ns.cloudflare.com.
=== TXT ===
"v=spf1 include:_spf.google.com include:mailgun.org -all"
"google-site-verification=abc123def456..."
"MS=ms84726311"
"stripe-verification=xyz789..."
=== SOA ===
ada.ns.cloudflare.com. dns.cloudflare.com. 2354...
=== CAA ===
0 issue "letsencrypt.org"
0 issue "digicert.com"

Lecture :

  • A : deux IPs dans le pool Cloudflare (104.21.x et 172.67.x). Le site est derrière Cloudflare — on ne verra pas l'IP réelle sans effort.
  • MX : Google Workspace. Aucun serveur mail à eux directement.
  • NS : ada.ns.cloudflare.com — Cloudflare gère le DNS aussi. Cohérent.
  • TXT :
    • SPF autorise Google et Mailgun. Deux services SaaS identifiés.
    • google-site-verification : ils utilisent Google Search Console.
    • MS= : ils utilisent Microsoft (Bing Webmaster, souvent).
    • stripe-verification : ils traitent des paiements Stripe. Ça veut dire du PCI-DSS quelque part.
  • CAA : seuls Let's Encrypt et DigiCert peuvent émettre. Bon signe côté hygiène.

En 2 minutes, on sait déjà : Cloudflare, Google Workspace, Mailgun, Stripe. On n'a envoyé aucun paquet à demo-corp.com.


Étape 2 — DMARC et posture email (1 minute)

dig +short _dmarc.demo-corp.com TXT

Sortie :

"v=DMARC1; p=none; rua=mailto:dmarc-reports@demo-corp.com"

Lecture : p=none. La politique DMARC est là mais ne fait rien. Résultat concret : un attaquant peut spoofer des emails prétendument envoyés par demo-corp.com, ces emails passeront chez le destinataire même s'ils échouent DMARC. C'est un vecteur de phishing à noter pour le module 6.

Enregistrez ça dans dns/dmarc.txt.


Étape 3 — Sous-domaines via crt.sh (3 minutes)

Certificate Transparency, la meilleure source pour la première salve de sous-domaines. On interroge en JSON, on nettoie avec jq :

curl -s 'https://crt.sh/?q=%25.demo-corp.com&output=json' \
| jq -r '.[].name_value' \
| tr '[:upper:]' '[:lower:]' \
| sed 's/^\*\.//' \
| sort -u \
> subs/from-crt.txt

wc -l subs/from-crt.txt

Sortie typique :

127 subs/from-crt.txt

Un extrait :

admin.demo-corp.com
api.demo-corp.com
api-dev.demo-corp.com
api-staging.demo-corp.com
beta.demo-corp.com
blog.demo-corp.com
cdn.demo-corp.com
customer.demo-corp.com
demo-corp.com
dev.demo-corp.com
docs.demo-corp.com
help.demo-corp.com
internal.demo-corp.com
jenkins.demo-corp.com
jira.demo-corp.com
mail.demo-corp.com
monitoring.demo-corp.com
old-admin.demo-corp.com
partners.demo-corp.com
prod.demo-corp.com
sso.demo-corp.com
staging.demo-corp.com
status.demo-corp.com
support.demo-corp.com
vpn.demo-corp.com
web.demo-corp.com
www.demo-corp.com

Trois lignes qui font sourire un attaquant :

  1. internal.demo-corp.com — un sous-domaine qui n'aurait pas dû sortir.
  2. jenkins.demo-corp.com — un serveur de CI/CD, historiquement mine de failles.
  3. old-admin.demo-corp.com — l'ancien panneau d'admin. Ça, ça sent l'oubli.

En 3 minutes, on est passé de 1 nom à 127.


Étape 4 — Recouper avec subfinder et amass -passive

subfinder interroge une vingtaine d'API tierces (Shodan, VirusTotal, SecurityTrails, DNSDumpster…) et rend une liste. Passif à 100 %.

subfinder -d demo-corp.com -silent -all -o subs/from-subfinder.txt
wc -l subs/from-subfinder.txt
143 subs/from-subfinder.txt

Idem, amass en mode passif :

amass enum -passive -d demo-corp.com -o subs/from-amass.txt

Ensuite on fusionne :

cat subs/from-*.txt | sort -u > subs/all-passive.txt
wc -l subs/all-passive.txt
178 subs/all-passive.txt

De 127 à 178. Chaque source a apporté quelques trouvailles. C'est pour ça qu'on recoupe.


Étape 5 — Résolution passive avec dnsx

Attention : dnsx résout les noms. Chaque résolution passe par un résolveur DNS public (Google 8.8.8.8 par défaut). C'est encore passif pour la cible si vous utilisez un résolveur qui n'appartient pas à la cible. Vérifiez que les NS de demo-corp.com ne sont pas vos résolveurs (c'est le cas ici : Cloudflare gère leur DNS, mais votre dnsx va interroger 1.1.1.1 de Cloudflare Public — c'est un service différent).

dnsx -l subs/all-passive.txt -a -resp -silent -r 1.1.1.1,8.8.8.8 \
-o subs/all-resolved.txt
head subs/all-resolved.txt

Sortie :

admin.demo-corp.com [104.21.44.15]
api.demo-corp.com [104.21.44.15]
api-dev.demo-corp.com [3.98.14.202]
api-staging.demo-corp.com [104.21.44.15]
internal.demo-corp.com [192.168.10.5]
jenkins.demo-corp.com [3.98.14.209]
old-admin.demo-corp.com [66.42.11.198]

Trois lignes qui parlent :

  • internal.demo-corp.com résout en 192.168.10.5 — une IP privée publiée dans le DNS public. Le sous-domaine est destiné à être accédé via VPN, mais sa présence dans le DNS confirme que ce service existe. À signaler.
  • api-dev.demo-corp.com sur 3.98.x.x — bloc AWS ca-central-1, pas derrière Cloudflare. C'est le vrai serveur exposé. Cible prioritaire pour la phase active.
  • old-admin.demo-corp.com sur 66.42.x.x — Vultr. Un serveur oublié, hors du CDN principal. Cible prioritaire aussi.

Notez ces trois lignes. Elles orienteront tout le module 4.


Étape 6 — Fingerprinting technologique passif

Attention : whatweb et wappalyzer chargent la page — c'est actif. Pour rester en passif strict, on utilise :

  • BuiltWith (via l'interface web depuis votre navigateur — mais votre navigateur va charger BuiltWith, pas la cible).
  • Shodan : shodan host <IP> renvoie ce que Shodan a déjà collecté.
shodan host 3.98.14.202 > tech/shodan-api-dev.txt
cat tech/shodan-api-dev.txt

Sortie type :

3.98.14.202
Hostnames: ec2-3-98-14-202.ca-central-1.compute.amazonaws.com
Country: Canada
City: Montréal
Organization: Amazon.com, Inc.

Open Ports: 22, 80, 443, 8080

22/tcp SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5
80/tcp nginx/1.18.0
443/tcp nginx/1.18.0 — TLSv1.3 — CN=api-dev.demo-corp.com
8080/tcp Django DEBUG page found

Ligne d'or : Django DEBUG page found. Shodan a déjà vu un mode debug Django exposé sur :8080. Un mode debug Django expose :

  • La stack complète en cas d'erreur.
  • Les variables d'environnement (donc souvent des clés secrètes).
  • Parfois SECRET_KEY complète.

On vient de trouver, sans envoyer un paquet à demo-corp.com, une faille probablement critique. On la confirmera en semaine 4.

Notez la découverte dans tech/decouvertes.md :

- [CRITIQUE] api-dev.demo-corp.com:8080 — Django en DEBUG (source : Shodan)
- [INFO] api-dev.demo-corp.com : Nginx 1.18, OpenSSH 8.2 sur Ubuntu 20

Étape 7 — Personnes clés (theHarvester + LinkedIn)

theHarvester -d demo-corp.com -b linkedin,bing,duckduckgo -l 500 \
-f people/harvester.html

theHarvester interroge des API tierces et LinkedIn (via Bing en général). Sortie type :

[*] Emails found: 34
admin@demo-corp.com
contact@demo-corp.com
j.dupuis@demo-corp.com
m.tremblay@demo-corp.com
...

[*] Hosts found:
(Idem, redondant avec ce qu'on a déjà)

[*] LinkedIn profiles (via Bing):
Marie Tremblay - CTO at Demo Corp
Jean Dupuis - Senior DevOps at Demo Corp
Étienne Roy - Support Lead at Demo Corp
...

Le pattern d'email ressort tout de suite : initiale.nom@demo-corp.com. À partir de LinkedIn, vous pouvez deviner l'email de la majorité des employés du client, sans jamais le leur demander.

Consolidez dans people/personnes.csv :

prenom,nom,titre,email,linkedin
Marie,Tremblay,CTO,m.tremblay@demo-corp.com,https://www.linkedin.com/in/marietremblay
Jean,Dupuis,Senior DevOps,j.dupuis@demo-corp.com,...
Étienne,Roy,Support Lead,e.roy@demo-corp.com,...

Ce fichier sert au module 6 (ingénierie sociale).


Étape 8 — Fuites publiques

# HaveIBeenPwned par domaine — nécessite une clé API (payante mais peu chère).
curl -s -H "hibp-api-key: $HIBP_KEY" \
"https://haveibeenpwned.com/api/v3/breacheddomain/demo-corp.com" \
| jq . > leaks/hibp.json

# Aperçu :
jq -r 'keys[] as $k | "\($k) → \(.[$k] | join(", "))"' leaks/hibp.json | head

Sortie :

j.dupuis  → Adobe, Collection#1, MyFitnessPal
support → Collection#1
etienne.roy → LinkedIn, Dropbox

Deux comptes techniques (j.dupuis, etienne.roy) ont déjà fuité dans des dumps publics. Si le client fait du password reuse — et statistiquement, un pentester peut compter là-dessus — on va pouvoir tenter du password spraying en semaine 5.

Complétez avec GitHub Search :

Cherchez des dépôts nommés demo-corp-*, scripts, backups, dotfiles. On y trouve régulièrement :

  • Un .env avec des secrets.
  • Des scripts avec des mots de passe en dur.
  • Des URLs internes.

Dans notre démo, un dotfiles public d'un ex-employé contient un fichier deploy.sh avec :

ssh deploy@old-admin.demo-corp.com -i ~/.ssh/deploy-key

Cible confirmée : old-admin.demo-corp.com, compte deploy. À exploiter en semaine 4.


Étape 9 — Archives (Wayback Machine)

curl -s "https://web.archive.org/cdx/search/cdx?url=demo-corp.com/*&output=json&limit=200" \
| jq -r '.[1:] | .[] | .[2]' \
| sort -u > archive/urls-historiques.txt

wc -l archive/urls-historiques.txt

Sortie :

612 archive/urls-historiques.txt

Un grep sur des mots-clés révélateurs :

grep -iE 'admin|backup|test|debug|swagger|api-doc|internal' archive/urls-historiques.txt
https://demo-corp.com/admin-old/
https://demo-corp.com/api/v1/debug
https://demo-corp.com/backup.sql (2019)
https://demo-corp.com/swagger.json

backup.sql en 2019 — probablement supprimé depuis, mais on vérifiera au module 4 : la Wayback Machine ne garantit pas la suppression côté serveur.


Étape 10 — Consolider la fiche

Ouvrez ~/osint/demo-corp/fiche-cible.md et remplissez avec ce qui précède. Cibles prioritaires à faire remonter en gras.

# Fiche cible — demo-corp.com  (2026-04-15)

## 1. Actifs confirmés
- Domaine racine : demo-corp.com (Cloudflare DNS + proxy)
- Sous-domaines : 178 collectés, dont :
- **api-dev.demo-corp.com → AWS ca-central-1 (3.98.14.202), Django DEBUG sur :8080**
- **old-admin.demo-corp.com → Vultr (66.42.11.198), compte deploy présumé**
- internal.demo-corp.com → 192.168.10.5 (privé), publié à tort
- jenkins.demo-corp.com → AWS
- jira.demo-corp.com → Atlassian Cloud (hors périmètre à préciser)

## 2. Périmètre à négocier avec le client
- internal.demo-corp.com (IP privée publiée) : ajouter au RoE ?
- Sous-domaines Atlassian et Google : hors périmètre.

## 3. Technologies
- Front (www) : Next.js derrière Cloudflare
- API prod : inconnu, filtré par Cloudflare
- API dev : Django, Nginx 1.18, Ubuntu 20 (source : Shodan)
- Messagerie : Google Workspace
- SaaS liés : Stripe, Mailgun, Atlassian, Sentry

## 4. Failles probables (à confirmer en semaine 4)
- CRITIQUE : Django DEBUG exposé sur api-dev:8080
- HAUTE : old-admin.demo-corp.com — panneau d'admin hérité
- MOYENNE : DMARC p=none → phishing spoofé possible
- MOYENNE : backup.sql (2019) — présent sur le serveur actuel ?

## 5. Personnes clés (source : LinkedIn + theHarvester)
- Marie Tremblay, CTO — m.tremblay@demo-corp.com
- Jean Dupuis, Sr DevOps — j.dupuis@demo-corp.com [fuite HIBP × 3]
- Étienne Roy, Support Lead — e.roy@demo-corp.com [fuite HIBP × 2]
+ 21 autres dans people/personnes.csv

## 6. Fuites publiques
- HIBP : 2 comptes à haute valeur avec réutilisation probable
- GitHub : dotfiles d'un ex-employé cite old-admin.demo-corp.com et compte deploy

## 7. Prochaine étape (module 4)
1. Confirmer Django DEBUG sur api-dev:8080 — 30 min.
2. Cartographier old-admin.demo-corp.com : ports, versions — 45 min.
3. Vérifier /backup.sql sur www — 5 min.
4. Password spraying prudent sur les 2 comptes HIBP — 30 min.

Bilan

En 90 minutes, sans envoyer aucun paquet à demo-corp.com :

  • On a 178 sous-domaines.
  • On a une faille critique presque certaine (Django DEBUG exposé).
  • On a deux cibles secondaires à haute valeur (old-admin, internal).
  • On a un plan d'attaque pour la semaine 4.
  • On a des comptes fuités exploitables plus tard.
  • La cible ne sait rien.

Voilà la puissance de l'OSINT bien menée. C'est le module qui rapporte le plus par minute investie.

Prochaine leçon : à vous. Vous choisissez un programme de bug bounty et vous refaites la même chose, en autonomie.