phpscan 1.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
phpscan-1.4.4/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Superstar Telecom LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
phpscan-1.4.4/PKG-INFO ADDED
@@ -0,0 +1,294 @@
1
+ Metadata-Version: 2.4
2
+ Name: phpscan
3
+ Version: 1.4.4
4
+ Summary: Free external PHP vulnerability scanner (php2shell / CVE-2026-109618, CVE-2026-109619) — passive fingerprinting plus limited, read-only path checks. No exploit probes.
5
+ Author: Superstar Telecom LLC
6
+ License: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
12
+ # phpscan — free open-source PHP vulnerability scanner
13
+
14
+ **Is your PHP version vulnerable to php2shell?** phpscan is a
15
+ free, disclosure-only scanner that answers that question for any
16
+ public website. It checks the PHP version a site discloses against
17
+ the fixed releases for **php2shell — CVE-2026-109618 /
18
+ CVE-2026-109619** (CVSS v4 9.2, unauthenticated remote code
19
+ execution in PHP core) — and, more generally, against the branch
20
+ floors in its advisory database.
21
+
22
+ It is the open-source scanner behind [phpatch.com](https://phpatch.com).
23
+
24
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
25
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
26
+ [![Dependencies: zero](https://img.shields.io/badge/dependencies-zero-brightgreen.svg)](#what-it-does)
27
+ [![Tests](https://github.com/PHPatch/phpscan/actions/workflows/tests.yml/badge.svg)](https://github.com/PHPatch/phpscan/actions/workflows/tests.yml)
28
+
29
+ ## What it does
30
+
31
+ - **Disclosure-only.** It reads what a site already discloses
32
+ publicly — `X-Powered-By` / `Server` headers, `PHPSESSID` cookies,
33
+ generator tags — plus a limited check for a publicly exposed
34
+ phpinfo page at a few well-known paths. It never sends an exploit
35
+ probe, a crafted payload, or anything designed to trigger the bug.
36
+ - **Honest verdicts.** If a site hides its version, the scanner
37
+ says so (VERSION HIDDEN) instead of guessing. If a build looks
38
+ like a distribution package, a below-floor version is reported
39
+ as a check signal (POSSIBLY VULNERABLE), because distros backport
40
+ fixes without changing the version string.
41
+ - **Public targets only.** The fetcher refuses loopback, private
42
+ and link-local addresses (including cloud metadata endpoints),
43
+ non-HTTP(S) schemes and ports other than 80/443, pins the
44
+ validated IP, and re-validates every redirect — it is designed
45
+ so it cannot be pointed at internal services. The refusals are
46
+ exercised by the test suite in `tests/` on every push.
47
+ - **Zero dependencies.** Python 3.11+ standard library only.
48
+
49
+ ## Verdicts
50
+
51
+ Every scan returns one JSON object per URL. The `verdict.status`
52
+ field uses the vocabulary below (shown here in its display form).
53
+ Actionable verdicts (`vulnerable`, `possibly_vulnerable`, `eol`)
54
+ also carry a `remediation` field naming the upgrade that fixes
55
+ them; patched verdicts carry none.
56
+
57
+ | Verdict | JSON `status` | Meaning |
58
+ |---|---|---|
59
+ | **VULNERABLE** | `vulnerable` | The disclosed version is below the fixed release for its branch, and a patched release exists. |
60
+ | **POSSIBLY VULNERABLE** | `possibly_vulnerable` | Below the floor, but the build looks like a distribution package — distros backport fixes, so this is a check signal, not proof. |
61
+ | **PATCHED** | `patched` | The disclosed version is at or above every advisory floor for its branch. (Not a general security guarantee — only "not below the fixed releases in the database.") |
62
+ | **END OF LIFE** | `eol` | The branch is below the advisory's EOL line (< 8.2 for php2shell): no patched release exists. The only complete remedies are a branch upgrade or taking the site offline. |
63
+ | **VERSION HIDDEN** | `indeterminate` | PHP is present but the version is not disclosed, so patch status cannot be confirmed from outside. Most well-run sites land here. |
64
+ | **NOT ASSESSED** | `not_assessed` | The branch is newer than the advisory database, so the scanner cannot judge it. |
65
+
66
+ Two more statuses cover the scan itself: `no_php_detected` (no PHP
67
+ signals found) and `unreachable` (the site did not answer, or the
68
+ target was refused by the safety policy).
69
+
70
+ ## Sample session
71
+
72
+ Recorded against a local test fixture that discloses
73
+ `X-Powered-By: PHP/8.3.20` — the output format is exactly what the
74
+ tool prints:
75
+
76
+ ```console
77
+ $ python3 -m phpscan http://fixture.example
78
+ {
79
+ "target": "http://fixture.example",
80
+ "reachable": true,
81
+ "http_status": 200,
82
+ "final_url": "http://fixture.example",
83
+ "error": null,
84
+ "signals": {
85
+ "x_powered_by": "PHP/8.3.20",
86
+ "server": "Apache/2.4.62"
87
+ },
88
+ "php_version": "8.3.20",
89
+ "version_source": "X-Powered-By",
90
+ "cms": [],
91
+ "phpinfo_exposed": false,
92
+ "verdict": {
93
+ "status": "vulnerable",
94
+ "version": "8.3.20",
95
+ "branch": "8.3",
96
+ "advisory": "php2shell-2026-10",
97
+ "cves": [
98
+ "CVE-2026-109618",
99
+ "CVE-2026-109619"
100
+ ],
101
+ "cvss_v4": 9.2,
102
+ "floor": "8.3.36",
103
+ "detail": "PHP 8.3.20 is below the patched release 8.3.36 for branch 8.3 (CVE-2026-109618, CVE-2026-109619)."
104
+ }
105
+ }
106
+ $ echo $?
107
+ 1
108
+ ```
109
+
110
+ Exit code 1 = an actionable finding. A site that runs PHP but
111
+ hides its version returns the VERSION HIDDEN verdict instead
112
+ (verdict block shown; the rest of the object lists the signals it
113
+ did see):
114
+
115
+ ```json
116
+ "verdict": {
117
+ "status": "indeterminate",
118
+ "detail": "PHP is present (fingerprinted) but the version is not disclosed, so the patch status cannot be confirmed from outside. Run the deep check (SSH, read-only) for a definitive verdict."
119
+ }
120
+ ```
121
+
122
+ ## Branch floors (php2shell)
123
+
124
+ A branch is PATCHED at or above its fixed release; anything below
125
+ it is VULNERABLE (or POSSIBLY VULNERABLE for distro builds):
126
+
127
+ | PHP branch | Fixed in |
128
+ |---|---|
129
+ | 8.2 | **8.2.35** |
130
+ | 8.3 | **8.3.36** |
131
+ | 8.4 | **8.4.27** |
132
+ | 8.5 | **8.5.12** |
133
+ | < 8.2 | No fix — **END OF LIFE** (branch upgrade or offline) |
134
+
135
+ The floors live in `phpscan/data/cves.json`, reviewed against
136
+ the php.net release announcements on every PHP security release
137
+ (see [Advisory data](#advisory-data)).
138
+
139
+ ## Install
140
+
141
+ ```bash
142
+ git clone https://github.com/PHPatch/phpscan.git
143
+ cd phpscan
144
+ # Python 3.11+ standard library only — no pip install, no dependencies.
145
+ ```
146
+
147
+ Or install it directly from GitHub, no clone needed:
148
+
149
+ ```bash
150
+ pip install git+https://github.com/PHPatch/phpscan.git
151
+ python3 -m phpscan https://your-site.com
152
+ ```
153
+
154
+ ## Run it
155
+
156
+ From the clone, run it right there — no install step:
157
+
158
+ ```bash
159
+ python3 -m phpscan https://your-site.com
160
+ ```
161
+
162
+ Prefer a zip? Download `phpscan.zip` from phpatch.com, then
163
+ either install it and run from anywhere:
164
+
165
+ ```bash
166
+ python3 -m pip install phpscan.zip
167
+ python3 -m phpscan https://your-site.com
168
+ ```
169
+
170
+ or unzip and run in place:
171
+
172
+ ```bash
173
+ unzip phpscan.zip
174
+ cd phpscan
175
+ python3 -m phpscan https://your-site.com
176
+ ```
177
+
178
+ Output is one JSON object per URL: the verdict, the disclosed PHP
179
+ version and where it was disclosed, and CMS fingerprints.
180
+
181
+ Exit codes (for scripts and CI): **0** — scanned, no actionable
182
+ finding; **1** — at least one target is `vulnerable`,
183
+ `possibly_vulnerable`, or on an end-of-life branch; **2** — usage
184
+ error, or a target could not be judged at all: unreachable, or
185
+ `not_assessed` (its PHP branch is newer than the advisory
186
+ database, so the scanner cannot judge it). With several targets,
187
+ the worst code wins.
188
+
189
+ Prefer a browser? The same scan runs free at
190
+ [phpatch.com](https://phpatch.com) and includes a PDF report.
191
+
192
+ ## How it compares
193
+
194
+ The php2shell scanners that appeared in October 2026 differ
195
+ mostly in **how they decide you are vulnerable** — and in whether
196
+ they try to trigger the bug to find out:
197
+
198
+ | Tool | Detection | Sends exploit triggers? | Remediation | License |
199
+ |---|---|---|---|---|
200
+ | **phpscan** (this repo) | Version fingerprint from what the site discloses; says "version hidden" instead of guessing | **No — never** | Via [PHP Patch Assurance](https://phpatch.com): snapshot-first patch, verify, rollback, evidence report | MIT |
201
+ | OpenAI php2shell-checker | Version fingerprint from `X-Powered-By` / `Server` headers only | No | None | Apache-2.0 |
202
+ | Searchlight Cyber php2shell-scanner | Behavioral — crafted multipart probes force PHP out of memory and watch for the crash | **Yes, deliberately** | None | No LICENSE file |
203
+ | SamJUK php2shell-check | Behavioral, local — observes how the installed PHP binary terminates at its memory limit | Only against a throwaway local CLI process | None | MIT |
204
+ | squiblyza php_vuln_scan | Version fingerprint from headers/markup, plus version-disclosure hunting | No | None | MIT |
205
+ | JoasASantos php2shell-scanner | Version fingerprint + subdomain recon + origin scan | Optional opt-in probe (README warns of DoS risk) | None | README states MIT; no LICENSE file |
206
+
207
+ Full criteria, the fairness notes (behavioral checks catch
208
+ backports; crash signals also misfire on some patched builds),
209
+ SSRF-safety comparison and an FAQ:
210
+ **[PHP vulnerability scanners compared](https://phpatch.com/compare)**.
211
+
212
+ ## What it doesn't do
213
+
214
+ - **It doesn't patch anything.** The scanner is read-only and
215
+ external; it cannot change your server.
216
+ - **It can't see a hidden version.** From outside, VERSION HIDDEN
217
+ is the honest end of the road — a definitive verdict for those
218
+ sites needs a read-only look on the server itself.
219
+ - **It doesn't monitor or alert.** It's a point-in-time check you
220
+ run; it won't notice next month's advisory for you.
221
+ - **It isn't a general security audit.** It judges the disclosed
222
+ PHP version against its advisory database — nothing more.
223
+
224
+ Patching, on-server verification, rollback, an evidence work
225
+ report, and monitoring are what the hosted service adds:
226
+ **[PHP Patch Assurance — phpatch.com](https://phpatch.com)**.
227
+
228
+ ## Guides and further reading
229
+
230
+ - **[Self-hoster guides](https://phpatch.com/guides)** — update
231
+ PHP in Docker and with apt, mod_php vs PHP-FPM, rollback,
232
+ health checks, version checks, end-of-life upgrades, and
233
+ patching without downtime, written from the patch flow the
234
+ service itself uses.
235
+ - **[php2shell fix guide](https://phpatch.com/threats/php2shell)**
236
+ — what php2shell is, who is affected, how to check and patch,
237
+ the fixed releases, and the primary sources.
238
+ - **[Case study: mitbbs.ai](https://phpatch.com/case-studies/mitbbs-ai)**
239
+ — how a bilingual news portal patched php2shell on disclosure
240
+ night: 8.3.35 to 8.3.36 under mod_php, about 10 seconds of
241
+ downtime, verified live, no compromise found.
242
+
243
+ ## Authorized use
244
+
245
+ Only scan sites you own or have permission to scan. The hosted
246
+ scanner at phpatch.com additionally enforces rate limits and an
247
+ opt-out blocklist for site operators (see the Terms, section 8).
248
+
249
+ ## Advisory data
250
+
251
+ `phpscan/data/cves.json` is the advisory database the scanner
252
+ judges against — branch floors, fixed releases, references and the
253
+ leak/exploitation timeline. Last updated 2026-10-22. Update
254
+ process: floors are reviewed against the php.net release
255
+ announcements on every PHP security release and at least monthly.
256
+ Corrections are welcome as pull requests; every change to this
257
+ file requires maintainer review (see CODEOWNERS), because it
258
+ changes the verdicts the scanner gives.
259
+
260
+ A verdict of `patched` means only that the disclosed version is
261
+ not below the fixed releases in this database — it is not a
262
+ general security guarantee. A version below a floor on a
263
+ distribution build (Ubuntu/Debian packages) is a "check" signal,
264
+ not proof: distros backport fixes without changing the upstream
265
+ version, and the scanner says so when it detects a distro build.
266
+
267
+ ## Support the project
268
+
269
+ phpscan is free and MIT-licensed, and the hosted scanner at
270
+ [phpatch.com](https://phpatch.com) is free for every site. If
271
+ the scanner, the threat desk or the daily Mega-Vuln Alert
272
+ reports helped you, you can chip in at
273
+ **[phpatch.com/donate](https://phpatch.com/donate)** — any
274
+ amount from $1, one-time, via Stripe. Donations fund phpscan
275
+ development, the free hosted scans and the public threat
276
+ research. Plainly stated on the page: PHPatch is operated by
277
+ Superstar Telecom LLC, a for-profit company, so donations are
278
+ voluntary support — not tax-deductible, and they buy no
279
+ product, service or entitlement.
280
+
281
+ ## Scanned by phpscan badge
282
+
283
+ If you scan your site with phpscan, you can show it:
284
+
285
+ [![Scanned by phpscan](https://img.shields.io/badge/scanned%20by-phpscan-blue.svg)](https://phpatch.com)
286
+
287
+ ```markdown
288
+ [![Scanned by phpscan](https://img.shields.io/badge/scanned%20by-phpscan-blue.svg)](https://phpatch.com)
289
+ ```
290
+
291
+ ## License
292
+
293
+ MIT. Not affiliated with the PHP Group. PHP is a trademark of the
294
+ PHP Group.
@@ -0,0 +1,283 @@
1
+ # phpscan — free open-source PHP vulnerability scanner
2
+
3
+ **Is your PHP version vulnerable to php2shell?** phpscan is a
4
+ free, disclosure-only scanner that answers that question for any
5
+ public website. It checks the PHP version a site discloses against
6
+ the fixed releases for **php2shell — CVE-2026-109618 /
7
+ CVE-2026-109619** (CVSS v4 9.2, unauthenticated remote code
8
+ execution in PHP core) — and, more generally, against the branch
9
+ floors in its advisory database.
10
+
11
+ It is the open-source scanner behind [phpatch.com](https://phpatch.com).
12
+
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
14
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
15
+ [![Dependencies: zero](https://img.shields.io/badge/dependencies-zero-brightgreen.svg)](#what-it-does)
16
+ [![Tests](https://github.com/PHPatch/phpscan/actions/workflows/tests.yml/badge.svg)](https://github.com/PHPatch/phpscan/actions/workflows/tests.yml)
17
+
18
+ ## What it does
19
+
20
+ - **Disclosure-only.** It reads what a site already discloses
21
+ publicly — `X-Powered-By` / `Server` headers, `PHPSESSID` cookies,
22
+ generator tags — plus a limited check for a publicly exposed
23
+ phpinfo page at a few well-known paths. It never sends an exploit
24
+ probe, a crafted payload, or anything designed to trigger the bug.
25
+ - **Honest verdicts.** If a site hides its version, the scanner
26
+ says so (VERSION HIDDEN) instead of guessing. If a build looks
27
+ like a distribution package, a below-floor version is reported
28
+ as a check signal (POSSIBLY VULNERABLE), because distros backport
29
+ fixes without changing the version string.
30
+ - **Public targets only.** The fetcher refuses loopback, private
31
+ and link-local addresses (including cloud metadata endpoints),
32
+ non-HTTP(S) schemes and ports other than 80/443, pins the
33
+ validated IP, and re-validates every redirect — it is designed
34
+ so it cannot be pointed at internal services. The refusals are
35
+ exercised by the test suite in `tests/` on every push.
36
+ - **Zero dependencies.** Python 3.11+ standard library only.
37
+
38
+ ## Verdicts
39
+
40
+ Every scan returns one JSON object per URL. The `verdict.status`
41
+ field uses the vocabulary below (shown here in its display form).
42
+ Actionable verdicts (`vulnerable`, `possibly_vulnerable`, `eol`)
43
+ also carry a `remediation` field naming the upgrade that fixes
44
+ them; patched verdicts carry none.
45
+
46
+ | Verdict | JSON `status` | Meaning |
47
+ |---|---|---|
48
+ | **VULNERABLE** | `vulnerable` | The disclosed version is below the fixed release for its branch, and a patched release exists. |
49
+ | **POSSIBLY VULNERABLE** | `possibly_vulnerable` | Below the floor, but the build looks like a distribution package — distros backport fixes, so this is a check signal, not proof. |
50
+ | **PATCHED** | `patched` | The disclosed version is at or above every advisory floor for its branch. (Not a general security guarantee — only "not below the fixed releases in the database.") |
51
+ | **END OF LIFE** | `eol` | The branch is below the advisory's EOL line (< 8.2 for php2shell): no patched release exists. The only complete remedies are a branch upgrade or taking the site offline. |
52
+ | **VERSION HIDDEN** | `indeterminate` | PHP is present but the version is not disclosed, so patch status cannot be confirmed from outside. Most well-run sites land here. |
53
+ | **NOT ASSESSED** | `not_assessed` | The branch is newer than the advisory database, so the scanner cannot judge it. |
54
+
55
+ Two more statuses cover the scan itself: `no_php_detected` (no PHP
56
+ signals found) and `unreachable` (the site did not answer, or the
57
+ target was refused by the safety policy).
58
+
59
+ ## Sample session
60
+
61
+ Recorded against a local test fixture that discloses
62
+ `X-Powered-By: PHP/8.3.20` — the output format is exactly what the
63
+ tool prints:
64
+
65
+ ```console
66
+ $ python3 -m phpscan http://fixture.example
67
+ {
68
+ "target": "http://fixture.example",
69
+ "reachable": true,
70
+ "http_status": 200,
71
+ "final_url": "http://fixture.example",
72
+ "error": null,
73
+ "signals": {
74
+ "x_powered_by": "PHP/8.3.20",
75
+ "server": "Apache/2.4.62"
76
+ },
77
+ "php_version": "8.3.20",
78
+ "version_source": "X-Powered-By",
79
+ "cms": [],
80
+ "phpinfo_exposed": false,
81
+ "verdict": {
82
+ "status": "vulnerable",
83
+ "version": "8.3.20",
84
+ "branch": "8.3",
85
+ "advisory": "php2shell-2026-10",
86
+ "cves": [
87
+ "CVE-2026-109618",
88
+ "CVE-2026-109619"
89
+ ],
90
+ "cvss_v4": 9.2,
91
+ "floor": "8.3.36",
92
+ "detail": "PHP 8.3.20 is below the patched release 8.3.36 for branch 8.3 (CVE-2026-109618, CVE-2026-109619)."
93
+ }
94
+ }
95
+ $ echo $?
96
+ 1
97
+ ```
98
+
99
+ Exit code 1 = an actionable finding. A site that runs PHP but
100
+ hides its version returns the VERSION HIDDEN verdict instead
101
+ (verdict block shown; the rest of the object lists the signals it
102
+ did see):
103
+
104
+ ```json
105
+ "verdict": {
106
+ "status": "indeterminate",
107
+ "detail": "PHP is present (fingerprinted) but the version is not disclosed, so the patch status cannot be confirmed from outside. Run the deep check (SSH, read-only) for a definitive verdict."
108
+ }
109
+ ```
110
+
111
+ ## Branch floors (php2shell)
112
+
113
+ A branch is PATCHED at or above its fixed release; anything below
114
+ it is VULNERABLE (or POSSIBLY VULNERABLE for distro builds):
115
+
116
+ | PHP branch | Fixed in |
117
+ |---|---|
118
+ | 8.2 | **8.2.35** |
119
+ | 8.3 | **8.3.36** |
120
+ | 8.4 | **8.4.27** |
121
+ | 8.5 | **8.5.12** |
122
+ | < 8.2 | No fix — **END OF LIFE** (branch upgrade or offline) |
123
+
124
+ The floors live in `phpscan/data/cves.json`, reviewed against
125
+ the php.net release announcements on every PHP security release
126
+ (see [Advisory data](#advisory-data)).
127
+
128
+ ## Install
129
+
130
+ ```bash
131
+ git clone https://github.com/PHPatch/phpscan.git
132
+ cd phpscan
133
+ # Python 3.11+ standard library only — no pip install, no dependencies.
134
+ ```
135
+
136
+ Or install it directly from GitHub, no clone needed:
137
+
138
+ ```bash
139
+ pip install git+https://github.com/PHPatch/phpscan.git
140
+ python3 -m phpscan https://your-site.com
141
+ ```
142
+
143
+ ## Run it
144
+
145
+ From the clone, run it right there — no install step:
146
+
147
+ ```bash
148
+ python3 -m phpscan https://your-site.com
149
+ ```
150
+
151
+ Prefer a zip? Download `phpscan.zip` from phpatch.com, then
152
+ either install it and run from anywhere:
153
+
154
+ ```bash
155
+ python3 -m pip install phpscan.zip
156
+ python3 -m phpscan https://your-site.com
157
+ ```
158
+
159
+ or unzip and run in place:
160
+
161
+ ```bash
162
+ unzip phpscan.zip
163
+ cd phpscan
164
+ python3 -m phpscan https://your-site.com
165
+ ```
166
+
167
+ Output is one JSON object per URL: the verdict, the disclosed PHP
168
+ version and where it was disclosed, and CMS fingerprints.
169
+
170
+ Exit codes (for scripts and CI): **0** — scanned, no actionable
171
+ finding; **1** — at least one target is `vulnerable`,
172
+ `possibly_vulnerable`, or on an end-of-life branch; **2** — usage
173
+ error, or a target could not be judged at all: unreachable, or
174
+ `not_assessed` (its PHP branch is newer than the advisory
175
+ database, so the scanner cannot judge it). With several targets,
176
+ the worst code wins.
177
+
178
+ Prefer a browser? The same scan runs free at
179
+ [phpatch.com](https://phpatch.com) and includes a PDF report.
180
+
181
+ ## How it compares
182
+
183
+ The php2shell scanners that appeared in October 2026 differ
184
+ mostly in **how they decide you are vulnerable** — and in whether
185
+ they try to trigger the bug to find out:
186
+
187
+ | Tool | Detection | Sends exploit triggers? | Remediation | License |
188
+ |---|---|---|---|---|
189
+ | **phpscan** (this repo) | Version fingerprint from what the site discloses; says "version hidden" instead of guessing | **No — never** | Via [PHP Patch Assurance](https://phpatch.com): snapshot-first patch, verify, rollback, evidence report | MIT |
190
+ | OpenAI php2shell-checker | Version fingerprint from `X-Powered-By` / `Server` headers only | No | None | Apache-2.0 |
191
+ | Searchlight Cyber php2shell-scanner | Behavioral — crafted multipart probes force PHP out of memory and watch for the crash | **Yes, deliberately** | None | No LICENSE file |
192
+ | SamJUK php2shell-check | Behavioral, local — observes how the installed PHP binary terminates at its memory limit | Only against a throwaway local CLI process | None | MIT |
193
+ | squiblyza php_vuln_scan | Version fingerprint from headers/markup, plus version-disclosure hunting | No | None | MIT |
194
+ | JoasASantos php2shell-scanner | Version fingerprint + subdomain recon + origin scan | Optional opt-in probe (README warns of DoS risk) | None | README states MIT; no LICENSE file |
195
+
196
+ Full criteria, the fairness notes (behavioral checks catch
197
+ backports; crash signals also misfire on some patched builds),
198
+ SSRF-safety comparison and an FAQ:
199
+ **[PHP vulnerability scanners compared](https://phpatch.com/compare)**.
200
+
201
+ ## What it doesn't do
202
+
203
+ - **It doesn't patch anything.** The scanner is read-only and
204
+ external; it cannot change your server.
205
+ - **It can't see a hidden version.** From outside, VERSION HIDDEN
206
+ is the honest end of the road — a definitive verdict for those
207
+ sites needs a read-only look on the server itself.
208
+ - **It doesn't monitor or alert.** It's a point-in-time check you
209
+ run; it won't notice next month's advisory for you.
210
+ - **It isn't a general security audit.** It judges the disclosed
211
+ PHP version against its advisory database — nothing more.
212
+
213
+ Patching, on-server verification, rollback, an evidence work
214
+ report, and monitoring are what the hosted service adds:
215
+ **[PHP Patch Assurance — phpatch.com](https://phpatch.com)**.
216
+
217
+ ## Guides and further reading
218
+
219
+ - **[Self-hoster guides](https://phpatch.com/guides)** — update
220
+ PHP in Docker and with apt, mod_php vs PHP-FPM, rollback,
221
+ health checks, version checks, end-of-life upgrades, and
222
+ patching without downtime, written from the patch flow the
223
+ service itself uses.
224
+ - **[php2shell fix guide](https://phpatch.com/threats/php2shell)**
225
+ — what php2shell is, who is affected, how to check and patch,
226
+ the fixed releases, and the primary sources.
227
+ - **[Case study: mitbbs.ai](https://phpatch.com/case-studies/mitbbs-ai)**
228
+ — how a bilingual news portal patched php2shell on disclosure
229
+ night: 8.3.35 to 8.3.36 under mod_php, about 10 seconds of
230
+ downtime, verified live, no compromise found.
231
+
232
+ ## Authorized use
233
+
234
+ Only scan sites you own or have permission to scan. The hosted
235
+ scanner at phpatch.com additionally enforces rate limits and an
236
+ opt-out blocklist for site operators (see the Terms, section 8).
237
+
238
+ ## Advisory data
239
+
240
+ `phpscan/data/cves.json` is the advisory database the scanner
241
+ judges against — branch floors, fixed releases, references and the
242
+ leak/exploitation timeline. Last updated 2026-10-22. Update
243
+ process: floors are reviewed against the php.net release
244
+ announcements on every PHP security release and at least monthly.
245
+ Corrections are welcome as pull requests; every change to this
246
+ file requires maintainer review (see CODEOWNERS), because it
247
+ changes the verdicts the scanner gives.
248
+
249
+ A verdict of `patched` means only that the disclosed version is
250
+ not below the fixed releases in this database — it is not a
251
+ general security guarantee. A version below a floor on a
252
+ distribution build (Ubuntu/Debian packages) is a "check" signal,
253
+ not proof: distros backport fixes without changing the upstream
254
+ version, and the scanner says so when it detects a distro build.
255
+
256
+ ## Support the project
257
+
258
+ phpscan is free and MIT-licensed, and the hosted scanner at
259
+ [phpatch.com](https://phpatch.com) is free for every site. If
260
+ the scanner, the threat desk or the daily Mega-Vuln Alert
261
+ reports helped you, you can chip in at
262
+ **[phpatch.com/donate](https://phpatch.com/donate)** — any
263
+ amount from $1, one-time, via Stripe. Donations fund phpscan
264
+ development, the free hosted scans and the public threat
265
+ research. Plainly stated on the page: PHPatch is operated by
266
+ Superstar Telecom LLC, a for-profit company, so donations are
267
+ voluntary support — not tax-deductible, and they buy no
268
+ product, service or entitlement.
269
+
270
+ ## Scanned by phpscan badge
271
+
272
+ If you scan your site with phpscan, you can show it:
273
+
274
+ [![Scanned by phpscan](https://img.shields.io/badge/scanned%20by-phpscan-blue.svg)](https://phpatch.com)
275
+
276
+ ```markdown
277
+ [![Scanned by phpscan](https://img.shields.io/badge/scanned%20by-phpscan-blue.svg)](https://phpatch.com)
278
+ ```
279
+
280
+ ## License
281
+
282
+ MIT. Not affiliated with the PHP Group. PHP is a trademark of the
283
+ PHP Group.
@@ -0,0 +1,15 @@
1
+ """phpscan — the free, open-source external PHP scanner from
2
+ PHP Patch Assurance (https://phpatch.com).
3
+
4
+ Passive fingerprinting plus limited, read-only checks of a few
5
+ well-known paths (the phpinfo exposure probes): it reads what a
6
+ site already discloses publicly (headers, generator tags, exposed
7
+ phpinfo pages) and judges any disclosed PHP version against the
8
+ advisory database in data/cves.json. It never runs exploit probes.
9
+
10
+ When a site hides its PHP version — most well-run sites do — the
11
+ verdict is an honest INDETERMINATE, with the path to a certain
12
+ answer (a read-only server check) explained at https://phpatch.com.
13
+ """
14
+
15
+ __version__ = "1.4.4"
@@ -0,0 +1,52 @@
1
+ """CLI: python3 -m phpscan <url> [more urls...]
2
+
3
+ Prints one JSON verdict object per URL.
4
+
5
+ Exit codes: 0 — scanned, no actionable finding; 1 — at least one
6
+ target is vulnerable, possibly vulnerable, or on an end-of-life
7
+ branch; 2 — usage error, or a target could not be judged at all:
8
+ unreachable, or `not_assessed` (its PHP branch is newer than the
9
+ advisory database, so the scanner cannot judge it). When several
10
+ targets are scanned, the worst code wins.
11
+ """
12
+
13
+ import json
14
+ import sys
15
+
16
+ from .scan import scan
17
+
18
+ _ACTIONABLE = ("vulnerable", "possibly_vulnerable", "eol")
19
+ _UNJUDGED = ("not_assessed", "unreachable")
20
+
21
+
22
+ def main(argv):
23
+ argv = [a for a in argv if a != ""]
24
+ if not argv:
25
+ print(__doc__)
26
+ return 2
27
+ if any(a in ("-h", "--help") for a in argv):
28
+ print(__doc__)
29
+ return 0
30
+ worst = 0
31
+ for url in argv:
32
+ try:
33
+ r = scan(url)
34
+ print(json.dumps(r, indent=1))
35
+ status = (r.get("verdict") or {}).get("status")
36
+ if status in _ACTIONABLE:
37
+ worst = max(worst, 1)
38
+ elif status in _UNJUDGED:
39
+ worst = max(worst, 2)
40
+ except Exception as e: # one bad target must not kill the run
41
+ print(json.dumps({"url": url, "error": str(e)}))
42
+ worst = max(worst, 2)
43
+ return worst
44
+
45
+
46
+ def cli():
47
+ """Console-script entry point (the `phpscan` command)."""
48
+ return main(sys.argv[1:])
49
+
50
+
51
+ if __name__ == "__main__":
52
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1 @@
1
+ {"advisories":[{"affected_sapis":["apache2handler (mod_php)","php-fpm","php-cgi","frankenphp","litespeed"],"cves":["CVE-2026-109618","CVE-2026-109619"],"cvss_v4":9.2,"distro_note":"Distribution packages may backport the fix without changing the upstream version string — verify via the package changelog or distro advisory, not the version alone. Third-party repositories lagged the fix on release day (Remi had no fixed build on 2026-10-21): when the repo has no fixed package, use the official container image or a source build, or apply the interim mitigations.","eol_below":"8.2","eol_note":"Branches below 8.2 receive no security fixes from the PHP project. There is NO patched release for them: the only remedies are a branch upgrade or taking the site offline (CERT-EU).","fixed_releases":{"8.2":"8.2.35","8.3":"8.3.36","8.4":"8.4.27","8.5":"8.5.12"},"id":"php2shell-2026-10","interim_mitigations":["Restrict access to the site (IP allow-list at the proxy / CDN) until patched — reduces exposure; it is not a fix","Enforce request-size limits at the reverse proxy / CDN edge as defense-in-depth","If no patched release can be deployed, take the site offline (CERT-EU guidance for unpatchable sites)"],"published":"2026-10-21","references":["https://www.php.net/releases/", "https://cert.europa.eu/publications/security-advisories/2026-018/", "https://www.cisa.gov/news-events/alerts/2026/10/21/critical-vulnerabilities-php-require-immediate-patching", "https://www.cve.org/CVERecord?id=CVE-2026-109618", "https://www.cve.org/CVERecord?id=CVE-2026-109619"],"summary":"Two critical flaws in PHP core: CVE-2026-109618 (remote code execution via out-of-memory corruption) and CVE-2026-109619 (remote code execution via stale global state). Both are exploitable over the network with no authentication. Any PHP application on a vulnerable build is exposed, regardless of the application itself.","timeline":"Vulnerability details leaked 2026-10-20. Fixed releases published 2026-10-21 (14:00 UTC). Exploitation was observed in the wild from 2026-10-21 07:43 UTC (Cloudflare data, reported by Sansec) — the exposure window opens at the leak, not at the patch.","title":"php2shell — unauthenticated remote code execution in PHP core"}],"source_notes":"Fixed releases published by the PHP project on 2026-10-21 (~14:00 UTC). CERT-EU advisory 2026-018, a CISA alert and an FBI alert circulated the same day; CERT-EU advised operators who cannot patch to take affected sites offline.","updated":"2026-10-22"}