Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
weblogchecker — Free access-log compromise analyzer: webshell interactions, exploitation patterns and brute-force bursts in your Apache/nginx logs - severity, confidence, remediation. Read-only. | Kitploit
Tools/GitHubGitHub/phpatch/weblogchecker
Defensive ToolsVulnerability AnalysisForensicsInformation GatheringWeb SecurityMalware AnalysisIntrusion DetectionIncident ResponseLog Analysis
GitHubphpatch/weblogchecker

weblogchecker

Free access-log compromise analyzer: webshell interactions, exploitation patterns and brute-force bursts in your Apache/nginx logs - severity, confidence, remediation. Read-only.

1617h 34m agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
View Repository
Share

weblogchecker

Your web server logs already know if you were attacked. weblogchecker reads them.

phpscan tells you whether your PHP is exposed. phpscan hunt searches the webroot for shells. weblogchecker answers the third question — did anyone actually use them? — from the one record most sites already have and nobody reads: the access log.

It streams Apache and nginx access logs you own, finds the interactions that matter — a webshell answering requests, a brute-force burst that ends in a redirect, an exploit pattern that got a 200 — and reports each one with severity, confidence, the actual log lines as evidence, and what to do about it.

weblogchecker analyze /var/log/apache2/access.log

Exit codes: 0 = no indicators, 1 = indicators found, 2 = usage error. Add --format json for machine-readable output, --since 2026-10-01 to limit the window. .gz logs are read directly; - reads stdin.

New in 0.2.0 — baseline diff. Signature lists only know shells that already have names. The shell that lands on your site has a random one. Give weblogchecker a trusted older log from the same site and it reports the executables that were never there before:

weblogchecker analyze access.log --baseline access.log.last-month

Every executable path (.php, .phtml, .cgi, .asp, .jsp…) that appears for the first time is scored on five weak signals from the log alone — answered 2xx/3xx, POST/PUT used, referrer-less, hit by at most 2 IPs, sitting under an upload/cache/temp directory — and reported as NEW with the signals, counts and log lines as evidence. First-seen alone is a low-severity note; severity climbs only as signals stack (details below), so a plugin you installed last week does not read as an incident.

Install

One line, from PyPI (Python 3.11+, standard library only — zero dependencies):

pip install weblogchecker

First PyPI release pending. Until the PyPI trusted publisher is configured, install the identical code from GitHub: pip install git+https://github.com/PHPatch/weblogchecker.git (or download the signed release tarball below). The pip install weblogchecker line above works as soon as the first PyPI release lands.

On systems that refuse with "externally-managed-environment" (Debian/Ubuntu and Homebrew Pythons), use pipx instead:

python3 -m pip install --user pipx   # if you don't have pipx yet
pipx install weblogchecker

Signed releases (sdist + wheel + PGP signatures + SBOM) are on the GitHub releases page. Verify signatures with the key in pgp-key.asc — fingerprint BAA1 586A AD37 18C0 CE41 D288 FE23 A624 54E3 5307. See SECURITY.md.

What it detects

Pattern in your logSeverity / confidenceWhy it matters
Known webshell (c99, r57, FilesMan, b374k, WSO) answering 2xxhigh / highThe shell exists and served a request
Same names probed but 404/403low / lowSomeone looked; nothing found — context, not alarm
eval-stdin.php (phpunit) answeringhigh / highThe UnitTest shell from the Oct 2026 php2shell wave executes POSTed code
Executable (.php etc.) inside /uploads/, /media/, /files/… answering, esp. POSThigh / highUpload dirs must never run code
POST/PUT to a static file (.jpg, .css…) answered 2xxhigh / mediumBrowsers don't POST to images; the "image" is often a script
Exploit pattern in the URI (traversal, eval(, php://, long base64 token) answered 2xxhigh / mediumThe attempt may have worked
Same patterns blocked / 404low / lowBackground noise; useful only as campaign context
Brute-force burst on wp-login.php / xmlrpc.php (≥20 POSTs / 10 min)medium / mediumOne IP, inhuman pace
A 302 inside that burst after repeated failureshigh / mediumThe shape of a correct password — possible takeover
Scanner user-agents (sqlmap, nuclei, nikto…)low / lowInformational; scanning is not compromise
Executable path absent from your --baseline log, answering requestslow → high / ≤ mediumThe unknown-named shell no blocklist knows; severity stacks with POSTs, missing referrers, few IPs, upload dirs

Every finding class carries remediation text: quarantine the file, rotate credentials, review everything that IP touched. Webshell findings point at the companion tool — phpscan hunt (pip install phpscan, github.com/PHPatch/phpscan) — which scans the webroot itself for the shells these log patterns point at.

Honesty rules

This tool was built under the same doctrine as phpscan:

  • Indicators, not verdicts. A finding says "this pattern appears in your log, with this confidence" — never "you were hacked". A clean result says "none of these patterns appear in this window" — never "you are safe". Attackers who arrive over SSH, a stolen session cookie, or a log the server never wrote leave nothing for this tool to find.
  • Failed attempts stay low. A 404 probe is someone knocking, not someone inside. Severity follows the server's answer, not the request's intent.
  • False-positive discipline is tested, not promised. The test suite ships a fixture of a normal busy WordPress day — admin logins, plugin updates, wp-cron, image uploads through wp-admin, Jetpack xmlrpc pings — and asserts it produces zero findings. A second fixture pair covers the baseline mode: a normal WordPress baseline plus a later log whose only novelties are a plugin installed through wp-admin, a contact form posting to a new handler, and a new post must produce zero medium/high findings. If a detector ever fires on ordinary admin work, that's a bug; please report it.
  • First-seen is a note, not an accusation. In baseline mode a new executable starts at low severity, climbs only when independent weak signals stack (never on first appearance alone), is capped when its first hit arrived from a wp-admin page — the shape of you installing something — and its confidence never exceeds medium. The finding says "this file was not in your baseline and behaves like this", with the counts to judge for yourself.
  • Read-only and offline. weblogchecker opens no network connections and never modifies the log it analyzes. Your logs — which reveal your visitors' IPs — never leave your machine.

Performance

Parsing is line-streaming: the file is never loaded into memory, and aggregation keeps at most five evidence lines per finding. Measured on this project's fixture generator (366,306 lines, 72 MB of realistic combined log): 7.6 seconds, 12.8 MB peak RSS on a modest VM. A 2 GB log is the same memory, proportionally more time.

Example

$ weblogchecker analyze access.log
weblogchecker 0.2.0 - access-log compromise analysis
Log: access.log
Lines read: 13 | parsed: 13 | unparseable (skipped): 0

Indicators found. These are leads for investigation, not proof of
compromise: work through the findings in severity order ...

SUMMARY: 10 findings (4 high, 1 medium, 5 low) across 9 incidents, 2 IPs flagged

INCIDENT TIMELINE (grouped by IP + path):
  [HIGH] 198.51.100.66 /wp-content/uploads/2026/10/c99.php
       classes: webshell-access, exec-in-upload-dir | requests: 6 | ...
  ...

1. [high severity / high confidence] Known webshell filename answered a request
   198.51.100.66 /wp-content/uploads/2026/10/c99.php - 3 request(s), ...
   | 198.51.100.66 - - [28/Oct/2026:03:13:40 +0000] "GET /wp-content/..." 200 ...
   Remediation: Treat the named file as a live webshell until you have
   proven otherwise. Locate it in the webroot and quarantine it ...

The family

Download Tool