
Scanner HTTP(S) asynchrone qui recherche des chaînes ou des expressions régulières dans les corps de réponse et les en-têtes, sur des hôtes, ports, plages CIDR et vhosts à certificat TLS.
# Description
Un outil Python asynchrone et rapide qui scanne des serveurs HTTP(S) et recherche des chaînes de caractères ou des motifs regex dans les corps et les en-têtes des réponses HTTP.
Il accepte des hôtes uniques, des URLs, des plages CIDR, des plages d'adresses IP ou des fichiers ; scanne plusieurs ports par cible (un seul, listes séparées par des virgules ou plages, détection automatique TLS vs simple par port) ; peut extraire et scanner les (v)hôtes basés sur le nom directement depuis les certificats TLS ; diffuse les correspondances en direct sur le terminal ; et peut écrire les résultats dans des fichiers journaux texte, CSV ou JSONL.
Il est conçu pour les grands scans : un cœur asynchrone pilote des milliers de connexions concurrentes, une vérification TCP préalable ignore les ports morts à moindre coût, des délais d'attente par hôte et globaux évitent qu'il ne reste bloqué sur des cibles lentes/mortes, et une exécution interrompue peut être reprise.
# Configuration requise
- Python 3.11+ sur un système POSIX (Linux, \*BSD, macOS - utilise `termios` et la gestion des signaux Unix d'asyncio)
- [httpx](https://pypi.org/project/httpx/) - `pip install -r requirements.txt` (ou `pip install httpx`)
- facultatif, utilisé automatiquement s'il est présent : `uvloop` (boucle d'événements plus rapide), `aiodns` (dns non bloquant pour `-r`), `h2` (HTTP/2 pour `-2`), `httpx[socks]` / socksio (proxies SOCKS)
httpgrep est un script unique autonome - exécutez simplement `./httpgrep.py`.
# Utilisation
```
$ httpgrep -H
__ __ __
/ /_ / /_/ /_____ ____ _________ ____
/ __ \/ __/ __/ __ \/ __ `/ ___/ _ \/ __ \
/ / / / /_/ /_/ /_/ / /_/ / / / __/ /_/ /
/_/ /_/\__/\__/ .___/\__, /_/ \___/ .___/
/_/ /____/ /_/
--== [ by nullsecurity.net ] ==--
usage
httpgrep -h <arg> -s <arg> [opts] | <misc>
target options
-h <hosts|file> - hôte unique/url ou plage hôte-/cidr ou fichier contenant
des hôtes ou fichier contenant des URLs, ex. : foobar.net,
192.168.0.1-192.168.0.254, 192.168.0.0/24, /tmp/hosts.txt
une liste d'hôtes séparée par des virgules fonctionne
aussi, ex. : 1.2.3.4,foo.net,10.0.0.0/24
NOTE : les hôtes peuvent aussi contenir ':<ports>' en ligne
de commande ou dans le fichier, où <ports> est un port
unique, une liste séparée par des virgules ou une plage,
ex. : foo.net:8080, foo.net:80,443, 10.0.0.1:1-1024
-p <ports|file> - port(s) auxquels se connecter : port unique, liste séparée
par des virgules, plage, ou fichier avec une spécification
par ligne, ex. : 80, 80,443,8080, 8000-8100,
/tmp/ports.txt (défaut : 80, ou 443 quand -t est donné)
-t - force TLS/SSL sur tous les ports. par défaut le schéma est
auto-détecté par port (http simple, bascule vers TLS si le
port le parle)
-u <URI|file> - URI ou URIs séparées par des virgules ou fichier avec URIs
(une par ligne) dans lesquelles rechercher les chaînes
données, ex. : /foobar/, /foo.html, /admin,/login,
/tmp/paths.txt (défaut : /)
-r - affiche le nom reverse-dns (PTR) des IPv4 scannées comme
étiquette ; l'ip reste la cible du scan (pas de dérive de
périmètre). non bloquant avec le paquet aiodns
http options
-X <method> - méthode de requête HTTP à utiliser, n'importe quelle casse
(défaut : get). utilisez '?' pour lister les méthodes
disponibles.
-a <user:pass> - identifiants d'authentification http (format : 'user:pass')
-U <UA> - définit un User-Agent personnalisé (défaut : dernier
ms edge, windows)
-A - utilise un user-agent aléatoire par requête
-R <headers> - définit des en-têtes personnalisés (format :
'foo=bar;lol=lulz;...')
-C <cookies> - définit des cookies (format : 'foo=bar;lol=lulz;...')
-F - ne suit pas les redirections HTTP
-L <num> - nombre maximal de redirections à suivre (défaut : 10 ;
ignoré avec -F)
-E - vérifie les certificats TLS/SSL (défaut : aucune
vérification)
-P <proxy> - utilise un proxy (format :
'[http|https|socks4|socks5]://host:port')
(socks nécessite le paquet 'httpx[socks]' / socksio)
-f <codes> - ne rapporte que les réponses avec les codes de statut HTTP
donnés, ex. : '200', '200,301,302'
-e <codes> - exclut les réponses avec les codes de statut HTTP donnés,
ex. : '404', '403,404,500'
-2 - essaie HTTP/2 (négocié par ALPN sur TLS, repli sur 1.1 ;
http simple reste en 1.1). nécessite le paquet 'h2'
search options
-s <str|file> - une chaîne/expression régulière unique ou plusieurs
chaînes/expressions régulières dans un fichier à trouver
dans les corps et en-têtes des réponses HTTP (voir -w),
ex. : 'tomcat 8', '/tmp/igot0daysforthese.txt'
-S <str|file> - inverse (grep -v) : supprime TOUTES les correspondances
d'une réponse si cette chaîne/expression régulière (ou
fichier) apparaît n'importe où dans son corps ou ses
en-têtes, ex. pour filtrer les pages d'erreur / 404
dynamiques
-w <where> - où rechercher : headers, body, ou headers,body
(défaut : headers,body)
-b <bytes> - nombre d'octets de contexte à afficher depuis une
correspondance dans le body (défaut : 64)
-m <size> - body maximal à lire + rechercher ; suffixe b/kb/mb, pas de
suffixe = kb, ex. : 512, 1mb, 262144b (défaut : 256kb)
-i - utilise une recherche insensible à la casse
-I - utilise une inversion insensible à la casse (pour -S)
scan options
-x <num> - nombre maximal de connexions concurrentes (async ;
défaut : 300). augmentez ulimit -n en conséquence pour des
valeurs très élevées
-c <seconds> - délai d'attente de lecture par hôte en secondes, plafonne
aussi le temps de lecture du body. la vérification TCP
préalable est plafonnée à 2s quoi qu'il arrive, donc les
hôtes filtrés/morts libèrent leur emplacement rapidement
(défaut : 3.0)
-G <seconds> - délai d'attente global : arrêt forcé de tout le scan après
N secondes (filet de sécurité contre tout blocage ;
défaut : aucun)
-y <num> - réessaie une sonde ayant échoué jusqu'à <num> fois
(défaut : 0). aide avec les hôtes instables à grande
échelle ; gardez-le petit
-1 - dès qu'un hôte a une correspondance, ignore ses sondes non
encore démarrées (au mieux ; les requêtes en vol se
terminent quand même, donc avec un -x élevé vous pouvez
encore voir quelques correspondances par hôte)
-z <size> - scanne les cibles dans un ordre aléatoire dans une fenêtre
à mémoire bornée de <size> ram (suffixe b/kb/mb/gb),
ex. : -z 1gb. évite que les énormes plages/fichiers
épuisent la mémoire
-Z <num> - plafonne la fenêtre -z à <num> cibles (défaut 2000000,
~267mo à ~140 octets chacune). plus = mélange plus large
sur les énormes plages, au prix de la ram et de la mise en
mémoire tampon au démarrage
-W - sauvegarde/reprise : sur ctrl+c écrit la progression dans
httpgrep.session ; relancez avec -W pour reprendre à
partir de là (sinon repart de zéro)
-T <0|1> - sonde aussi les (v)hôtes du certificat (CN + SAN) comme
requêtes supplémentaires en plus du scan direct. 0 = via
l'en-tête Host sur la même ip (dans le périmètre) ; 1 =
AUSSI par nom dns/SNI (peut sortir du périmètre).
nécessite TLS (url https, -t, ou un port *443).
output options
-l <file> - journalise les correspondances trouvées dans <file>.<fmt>
selon le format -O choisi (ex. : -l out -O csv,jsonl =>
out.csv, out.jsonl)
-O <formats> - format(s) de fichier journal, liste séparée par des
virgules : txt, csv, jsonl (défaut : txt ; utilisez '?'
pour lister). la sortie terminal reste toujours lisible
par un humain.
-v - verbeux : affiche chaque url au fur et à mesure de son
scan
-7 - échappe le non-ASCII dans la sortie terminal en \xNN,
afin qu'un corps de réponse hostile ne puisse pas corrompre
votre terminal (les journaux restent bruts)
misc options
-H - affiche l'aide
-V - affiche les informations de version
examples
# grep 'apache' dans les en-têtes et le body d'un hôte unique
$ httpgrep -h foobar.net -s apache
# scanne une plage CIDR sur le port 8080, recherche 'tomcat' dans le body
# uniquement
$ httpgrep -h 192.168.0.0/24 -p 8080 -s tomcat -w body
# scanne un hôte sur plusieurs ports et une plage de ports pour 'jenkins'
$ httpgrep -h 192.168.0.10 -p 80,443,8080,8000-8100 -s jenkins -i
# scanne une liste d'hôtes, fichier de chaînes de recherche, journalise les
# correspondances (-> /tmp/out.txt)
$ httpgrep -h /tmp/hosts.txt -s /tmp/strings.txt -x 200 -l /tmp/out
# grep 'admin' insensible à la casse sur plusieurs URIs via TLS
$ httpgrep -h foobar.net -t -u /admin,/login,/dashboard -s admin -i
# scanne une plage d'IPs, reverse DNS, ne rapporte que les réponses 200
$ httpgrep -h 10.0.0.1-10.0.0.254 -s 'powered by' -r -f 200
# recherche uniquement dans les en-têtes, ne suit pas les redirections,
# sortie verbeuse
$ httpgrep -h foobar.net -s 'X-Powered-By' -w headers -F -v
# grep 'admin', mais supprime les pages d'erreur dynamiques (inversion,
# insensible à la casse)
$ httpgrep -h 192.168.0.0/24 -s admin -i -S 'error|not found' -I
# via un proxy, UA personnalisé, recherche de chaînes de version
$ httpgrep -h /tmp/hosts.txt -s 'nginx/1\.' -P http://127.0.0.1:8080 -U 'curl/8.0'
# grand scan reprenable : ctrl+c sauvegarde l'état, relancez avec -W pour
# continuer ; plafonnez aussi toute l'exécution à 1 heure comme filet de
# sécurité contre les blocages
$ httpgrep -h 10.0.0.0/16 -p 80,443 -s admin -W -G 3600
```
# Sortie
Les correspondances sont affichées en direct, une par ligne :
```
[*] <url> | [vhost] | <status> | <type> | <match>
```
- `<url>` - l'URL scannée (`scheme://host:port/uri`).
- `<vhost>` - présent avec `-T` (le (v)hôte du certificat essayé via l'en-tête `Host`) ou `-r` (le nom PTR de l'ip scannée) ; vide pour les scans directs.
- `<status>` - le code de statut de la réponse HTTP (après les redirections).
- `<type>` - `body` ou `header`.
- `<match>` - hit dans le body : une courte fenêtre représentée depuis la correspondance (`-b` octets) ; hit dans l'en-tête : `nom: valeur`.
Le terminal affiche toujours cette forme lisible par un humain. Avec `-l <base>` les mêmes correspondances sont reflétées dans `<base>.<fmt>` pour chaque format `-O` - `txt` (ces lignes), `csv` (lignes `url,vhost,status,type,match` avec un en-tête), `jsonl` (un objet JSON par correspondance).
Lors d'un scan multi-cibles, une ligne de statut en direct est affichée (épinglée en bas sur un tty, en lignes simples quand la sortie est redirigée) :
```
[+] wait bitch, scanning: <targets> | <scanned>/<total> | <pct>% | <n> hits
```
`<total>` est le nombre de cibles (cidrs/plages calculés, non développés) ; `<n> hits` est le nombre cumulé de lignes de correspondance émises jusqu'ici.
# Auteur
noptrix
# Notes
- code quick'n'dirty
- httpgrep est déjà empaqueté et disponible pour [BlackArch Linux](https://www.blackarch.org/)
- Mes branches master sont toujours stables ; les branches dev sont créées pour le travail en cours.
- Tout ce que je publie publiquement est officiellement annoncé et publié via [nullsecurity.net](https://www.nullsecurity.net).
# Licence
Vérifiez docs/LICENSE.
# Avertissement
Nous soulignons par la présente que tout ce qui concerne le hacking sur [nullsecurity.net](http://nullsecurity.net) n'est qu'à des fins éducatives. Nous ne sommes pas responsables des dommages. Vous êtes responsable de vos propres actions.