
Analizzatore gratuito di compromissione dei log di accesso: interazioni con webshell, pattern di sfruttamento e raffiche di brute-force nei tuoi log Apache/nginx - gravità, affidabilità, rimedio. Sola lettura.
I log del tuo server web sanno già se sei stato attaccato. weblogchecker li legge.
phpscan ti dice se il tuo PHP è esposto. phpscan hunt cerca le shell nella
webroot. weblogchecker risponde alla terza domanda — qualcuno le ha
effettivamente usate? — a partire dall'unica registrazione che quasi tutti i siti già possiedono e che nessuno
legge: l'access log.
Elabora in streaming i log di accesso Apache e nginx di tua proprietà, individua le interazioni che contano — una webshell che risponde alle richieste, un picco di brute-force che termina in un redirect, un pattern di exploit che ha ottenuto un 200 — e segnala ciascuna con gravità, affidabilità, le effettive righe di log come prova e cosa fare al riguardo.
weblogchecker analyze /var/log/apache2/access.log
Codici di uscita: 0 = nessun indicatore, 1 = indicatori trovati, 2 = errore di utilizzo.
Aggiungi --format json per un output leggibile dalla macchina, --since 2026-10-01 per
limitare l'intervallo. I log .gz vengono letti direttamente; - legge da stdin.
Novità in 0.2.0 — baseline diff. Gli elenchi di firme conoscono solo le shell che hanno già un nome. La shell che atterra sul tuo sito ne ha uno casuale. Fornisci a weblogchecker un log più vecchio e affidabile dallo stesso sito e segnalerà gli eseguibili che non erano mai stati presenti prima:
weblogchecker analyze access.log --baseline access.log.last-month
Ogni percorso eseguibile (.php, .phtml, .cgi, .asp, .jsp…) che appare per
la prima volta viene valutato in base a cinque segnali deboli ricavati dal solo log —
risposta 2xx/3xx, uso di POST/PUT, assenza di referrer, richiesto da al massimo 2 IP,
posizionato sotto una directory upload/cache/temp — e segnalato come NEW
con i segnali, i conteggi e le righe di log come evidenza. La sola prima apparizione è
una nota di bassa gravità; la gravità aumenta solo man mano che i segnali si accumulano (dettagli
sotto), quindi un plugin installato la settimana scorsa non viene letto come un
incidente.
Una riga, da PyPI (Python 3.11+, solo libreria standard — zero dipendenze):
pip install weblogchecker
Prima release su PyPI in attesa. Finché il trusted publisher di PyPI non è configurato, installa il codice identico da GitHub:
pip install git+https://github.com/PHPatch/weblogchecker.git(oppure scarica il tarball firmato della release qui sotto). La rigapip install weblogcheckerqui sopra funziona non appena viene pubblicata la prima release su PyPI.
Sui sistemi che rifiutano con "externally-managed-environment" (Python di Debian/Ubuntu e Homebrew), usa invece pipx:
python3 -m pip install --user pipx # if you don't have pipx yet
pipx install weblogchecker
Le release firmate (sdist + wheel + firme PGP + SBOM) sono disponibili nella
pagina delle release su GitHub.
Verifica le firme con la chiave in pgp-key.asc — fingerprint
BAA1 586A AD37 18C0 CE41 D288 FE23 A624 54E3 5307. Vedi SECURITY.md.
| Pattern nel tuo log | Gravità / affidabilità | Perché è importante |
|---|---|---|
| Webshell nota (c99, r57, FilesMan, b374k, WSO) che risponde 2xx | alta / alta | La shell esiste e ha servito una richiesta |
| Gli stessi nomi sondati ma con 404/403 | bassa / bassa | Qualcuno ha guardato; non ha trovato nulla — contesto, non allarme |
eval-stdin.php (phpunit) che risponde | alta / alta | La shell UnitTest dell'ondata php2shell di ottobre 2026 esegue codice inviato via POST |
Eseguibile (.php ecc.) all'interno di /uploads/, /media/, /files/… che risponde, spec. a POST | alta / alta | Le directory di upload non devono mai eseguire codice |
| POST/PUT verso un file statico (.jpg, .css…) con risposta 2xx | alta / media | I browser non inviano POST alle immagini; l'"immagine" è spesso uno script |
Pattern di exploit nell'URI (traversal, eval(, php://, token base64 lungo) con risposta 2xx | alta / media | Il tentativo potrebbe aver avuto successo |
| Gli stessi pattern bloccati / 404 | bassa / bassa | Rumore di fondo; utile solo come contesto di campagna |
| Raffica di brute-force su wp-login.php / xmlrpc.php (≥20 POST / 10 min) | media / media | Un solo IP, ritmo inumano |
| Un 302 all'interno di quella raffica dopo ripetuti fallimenti | alta / media | La forma di una password corretta — possibile takeover |
| User-agent di scanner (sqlmap, nuclei, nikto…) | bassa / bassa | Informativo; scansionare non è compromissione |
Percorso eseguibile assente dal tuo log --baseline, che risponde alle richieste | bassa → alta / ≤ media | La shell dal nome sconosciuto che nessuna blocklist conosce; la gravità sale con POST, referrer mancanti, pochi IP, directory di upload |
Ogni classe di rilevamento include un testo di remediation: metti in quarantena il file, ruota
le credenziali, esamina tutto ciò che quell'IP ha toccato. I rilevamenti di webshell rimandano
allo strumento complementare — phpscan hunt (pip install phpscan,
github.com/PHPatch/phpscan) — che
scansiona la webroot stessa alla ricerca delle shell a cui questi pattern di log rimandano.
Questo strumento è stato costruito secondo la stessa dottrina di phpscan:
L'analisi avviene in streaming riga per riga: il file non viene mai caricato in memoria e l'aggregazione mantiene al massimo cinque righe di evidenza per ogni rilevamento. Misurato sul generatore di fixture di questo progetto (366.306 righe, 72 MB di log combinato realistico): 7,6 secondi, 12,8 MB di RSS di picco su una VM modesta. Un log da 2 GB richiede la stessa memoria e un tempo proporzionalmente maggiore.
$ weblogchecker analyze access.log
weblogchecker 0.2.0 - access-log compromise analysis
Log: access.log
Lines read: 13 | parsed: 13 | unparseable (skipped): 0