
Apache/nginx लॉग में webshell इंटरैक्शन, शोषण पैटर्न और ब्रूट-फ़ोर्स बर्स्ट का विश्लेषण करने वाला निःशुल्क एक्सेस-लॉग समझौता विश्लेषक - गंभीरता, विश्वास और उपचार। केवल-पठन।
आपके वेब सर्वर लॉग्स पहले से ही जानते हैं कि आप पर हमला हुआ था या नहीं। weblogchecker उन्हें पढ़ता है।
phpscan आपको बताता है कि आपका PHP उजागर है या नहीं। phpscan hunt वेबरूट में
शेल्स की खोज करता है। weblogchecker तीसरे प्रश्न का उत्तर देता है — क्या किसी ने
वास्तव में उनका उपयोग किया? — उस एक रिकॉर्ड से जो अधिकांश साइटों के पास पहले से होता है और जिसे कोई नहीं
पढ़ता: एक्सेस लॉग।
यह Apache और nginx एक्सेस लॉग्स को स्ट्रीम करता है जो आपके स्वयं के हैं, उन इंटरैक्शन्स को ढूँढता है जो मायने रखते हैं — अनुरोधों का उत्तर देता एक वेबशेल, एक ब्रूट-फ़ोर्स बर्स्ट जो रीडायरेक्ट पर समाप्त होता है, एक एक्सप्लॉइट पैटर्न जिसे 200 मिला — और प्रत्येक की रिपोर्ट गंभीरता, विश्वास, साक्ष्य के रूप में वास्तविक लॉग लाइनों, और इसके बारे में क्या करना है के साथ करता है।
weblogchecker analyze /var/log/apache2/access.log
एग्ज़िट कोड: 0 = कोई संकेतक नहीं, 1 = संकेतक मिले, 2 = उपयोग त्रुटि।
मशीन-पठनीय आउटपुट के लिए --format json जोड़ें, विंडो को सीमित करने के लिए
--since 2026-10-01 जोड़ें। .gz लॉग सीधे पढ़े जाते हैं; - stdin पढ़ता है।
0.2.0 में नया — बेसलाइन डिफ। सिग्नेचर सूचियाँ केवल उन्हीं शेल्स को जानती हैं जिनके नाम पहले से हैं। जो शेल आपकी साइट पर आता है, उसका नाम यादृच्छिक होता है। weblogchecker को उसी साइट का कोई विश्वसनीय पुराना लॉग दें और यह उन एक्ज़ीक्यूटेबल्स की रिपोर्ट करता है जो पहले कभी वहाँ नहीं थे:
weblogchecker analyze access.log --baseline access.log.last-month
हर executable path (.php, .phtml, .cgi, .asp, .jsp…) जो पहली बार
दिखाई देता है, उसे केवल लॉग से पाँच कमज़ोर संकेतों पर स्कोर किया जाता है —
2xx/3xx के साथ उत्तर दिया गया, POST/PUT का उपयोग, referrer-रहित, अधिकतम 2 IPs द्वारा हिट,
upload/cache/temp डायरेक्टरी के अंतर्गत स्थित — और संकेतों, गणनाओं और लॉग पंक्तियों को
प्रमाण के रूप में NEW के रूप में रिपोर्ट किया जाता है। केवल पहली बार देखा जाना
कम-गंभीरता वाला नोट है; गंभीरता केवल तब बढ़ती है जब संकेत एकत्र होते हैं (विवरण
नीचे), इसलिए पिछले सप्ताह आपके द्वारा इंस्टॉल किया गया प्लगइन किसी घटना के रूप में नहीं पढ़ा जाता।
एक पंक्ति, PyPI से (Python 3.11+, केवल मानक लाइब्रेरी — शून्य निर्भरताएँ):
pip install weblogchecker
पहला PyPI रिलीज़ लंबित है। जब तक PyPI trusted publisher कॉन्फ़िगर नहीं हो जाता, GitHub से समान कोड इंस्टॉल करें:
pip install git+https://github.com/PHPatch/weblogchecker.git(या नीचे दिया गया signed release tarball डाउनलोड करें)। ऊपर दी गईpip install weblogcheckerलाइन पहला PyPI रिलीज़ आते ही काम करने लगेगी।
उन सिस्टम्स पर जो "externally-managed-environment" कहकर मना कर देते हैं (Debian/Ubuntu और Homebrew Pythons), वहाँ इसके बजाय pipx का उपयोग करें:
python3 -m pip install --user pipx # if you don't have pipx yet
pipx install weblogchecker
हस्ताक्षरित रिलीज़ (sdist + wheel + PGP हस्ताक्षर + SBOM) GitHub रिलीज़ पृष्ठ पर उपलब्ध हैं। pgp-key.asc में दी गई कुंजी से हस्ताक्षर सत्यापित करें — फ़िंगरप्रिंट BAA1 586A AD37 18C0 CE41 D288 FE23 A624 54E3 5307। SECURITY.md देखें।
| आपके लॉग में पैटर्न | गंभीरता / विश्वास | यह क्यों मायने रखता है |
|---|---|---|
| ज्ञात webshell (c99, r57, FilesMan, b374k, WSO) जो 2xx लौटा रहा है | उच्च / उच्च | शेल मौजूद है और उसने एक अनुरोध पूरा किया |
| वही नाम प्रोब किए गए लेकिन 404/403 | निम्न / निम्न | किसी ने देखा; कुछ नहीं मिला — संदर्भ, अलार्म नहीं |
eval-stdin.php (phpunit) उत्तर दे रहा है | उच्च / उच्च | अक्टूबर 2026 php2shell लहर का UnitTest शेल POST किए गए कोड को निष्पादित करता है |
/uploads/, /media/, /files/… के अंदर निष्पादन योग्य (.php आदि) उत्तर दे रहा है, विशेषकर POST पर | उच्च / उच्च | अपलोड डायरेक्टरीज़ को कभी भी कोड नहीं चलाना चाहिए |
| स्थिर फ़ाइल (.jpg, .css…) पर POST/PUT का 2xx उत्तर | उच्च / मध्यम | ब्राउज़र इमेज पर POST नहीं करते; "इमेज" अक्सर एक स्क्रिप्ट होती है |
URI में एक्सप्लॉइट पैटर्न (traversal, eval(, php://, लंबा base64 टोकन) का 2xx उत्तर | उच्च / मध्यम | प्रयास सफल हो सकता है |
| वही पैटर्न ब्लॉक किए गए / 404 | निम्न / निम्न | पृष्ठभूमि शोर; केवल अभियान संदर्भ के रूप में उपयोगी |
| wp-login.php / xmlrpc.php पर ब्रूट-फ़ोर्स विस्फोट (≥20 POSTs / 10 मिनट) | मध्यम / मध्यम | एक IP, अमानवीय गति |
| उस विस्फोट के भीतर बार-बार विफलताओं के बाद एक 302 | उच्च / मध्यम | सही पासवर्ड का स्वरूप — संभावित अधिग्रहण |
| स्कैनर user-agents (sqlmap, nuclei, nikto…) | निम्न / निम्न | सूचनात्मक; स्कैनिंग समझौता नहीं है |
निष्पादन योग्य पथ आपके --baseline लॉग में अनुपस्थित, अनुरोधों का उत्तर दे रहा है | निम्न → उच्च / ≤ मध्यम | वह अज्ञात-नाम वाला शेल जिसे कोई ब्लॉकलिस्ट नहीं जानती; गंभीरता POSTs, अनुपस्थित referrers, कम IPs, अपलोड डायरेक्टरीज़ के साथ बढ़ती है |
प्रत्येक फ़ाइंडिंग श्रेणी में उपचार पाठ शामिल है: फ़ाइल को क्वारंटीन करें, क्रेडेंशियल रोटेट करें, उस IP ने जो कुछ भी छुआ उसकी समीक्षा करें। Webshell फ़ाइंडिंग्स साथी टूल की ओर इशारा करती हैं — phpscan hunt (pip install phpscan, github.com/PHPatch/phpscan) — जो इन लॉग पैटर्नों द्वारा इंगित शेल्स के लिए स्वयं webroot को स्कैन करता है।
यह टूल phpscan के समान सिद्धांत के अंतर्गत बनाया गया था:
पार्सिंग लाइन-स्ट्रीमिंग है: फ़ाइल को कभी भी मेमोरी में लोड नहीं किया जाता, और एग्रीगेशन प्रति फ़ाइंडिंग अधिकतम पाँच एविडेंस लाइनें रखता है। इस प्रोजेक्ट के फ़िक्स्चर जनरेटर (366,306 लाइनें, यथार्थवादी संयुक्त लॉग का 72 MB) पर मापा गया: एक साधारण VM पर 7.6 सेकंड, 12.8 MB पीक RSS। 2 GB का लॉग भी समान मेमोरी लेता है, समानुपातिक रूप से अधिक समय लेता है।
$ 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 | ...
...