This is a loaded nail gun left inside the fenced job site, not on the sidewalk
CVE-2025-0213 is an unrestricted file upload flaw in Campcodes Project Management System 1.0, specifically in /forms/update_forms.php?action=change_pic2&id=4. The published proof of concept shows the handler accepting a user-supplied file and moving it into ../images/ without extension or content validation; if that directory executes PHP, an authenticated user can turn an image upload into a web shell and likely remote code execution on the web server. Publicly stated affected versioning is just 1.0, and I could not find an authoritative vendor-fixed release.
The vendor/NVD baseline of MEDIUM 6.3 is directionally right but slightly generous for enterprise prioritization. The decisive friction is not exploit complexity; it is attacker position: this is authenticated remote against a niche downloadable PHP/MySQL project, which implies the adversary already has credentials or a foothold into the app. That sharply narrows real-world reach, even though the post-auth impact can be ugly on a misconfigured PHP host.
4 steps from start to impact.
Get a valid PMS session
PR:L, and the PoC includes a PHPSESSID cookie, so the attacker is not walking in unauthenticated from the internet. Weaponized tooling here is ordinary browser automation, curl, or Burp Suite replay against the login flow and then the upload endpoint.- A reachable Campcodes Project Management System 1.0 instance
- Valid low-privilege application credentials or a hijacked authenticated session
- Knowledge of the app path such as
/construction_pms/
- This is post-auth, so it usually depends on credential theft, password reuse, or another bug first
- Campcodes is a niche downloadable project, not a mainstream enterprise platform with huge exposure
- Many deployments are lab, student, or internal-only installs rather than hardened public apps
Upload a PHP payload through change_pic2
curl, the attacker sends a multipart POST to /forms/update_forms.php?action=change_pic2&id=<project_id> with a file like test.php. The published code path uses basename() and move_uploaded_file() but does not enforce an allowlist of safe extensions or MIME types before writing into ../images/.- The vulnerable
change_pic2code path exists informs/update_forms.php - The authenticated user can reach the project picture update action
- The server accepts multipart form uploads
- If the upload directory blocks script execution, impact falls from code execution to stored file placement
- Local hardening like extension allowlists, web-tier rewrite rules, or PHP execution bans in
images/breaks the exploit - Some app roles may not be allowed to edit project records even with a valid session
.php, double extensions, or application/x-php. EDR/web-shell detection may fire when the dropped file is later executed, but many scanners miss this if they only test unauthenticated surfaces.Trigger the uploaded web shell
x=. Tooling is trivial: browser, curl, or web-shell clients. At that point the bug becomes server-side command execution in the security context of the PHP worker.- The uploaded file lands in a web-accessible path
- PHP execution is enabled for that path
- The payload is not removed by AV, EDR, or file-integrity monitoring
- Least-privilege PHP-FPM pools and containerized deployments can limit blast radius
- Non-executable uploads, read-only containers, or noexec-style controls stop the code-execution jump
- Good EDR often catches the web shell only when it starts spawning system commands
.php files, EDR alerts on php-fpm/httpd spawning shells, and file-integrity monitoring on the webroot.Pivot from app compromise to host impact
linpeas, pspy, local shell one-liners, or simple database dumps. The eventual blast radius depends much more on host hardening than on the original upload bug.- Command execution from the web tier
- Interesting secrets or excessive permissions on disk
- Weak host segmentation or privilege boundaries
- A locked-down web account can confine the attacker to one app and one database
- Secrets vaulting, network segmentation, and EDR containment sharply reduce follow-on value
- If the app is a throwaway internal demo, attacker ROI is low
The supporting signals.
| In-the-wild status | No confirmed active exploitation in the sources reviewed. CISA's ADP enrichment marks exploitation as poc, not observed-in-the-wild. |
|---|---|
| KEV status | Not listed in CISA KEV as reviewed; no KEV date applies. |
| Proof of concept | Public PoC exists: shaturo1337/POCs publishes an HTTP request and PHP web-shell payload for this exact endpoint. |
| EPSS | Low exploit probability. User-provided EPSS is 0.00112; a public aggregator snapshot shows roughly 0.08% probability and about the 24th percentile, which is consistent with low operational interest. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L means network reachable but authenticated. In practice, PR:L is the whole story: this is usually a post-compromise or stolen-credential issue, not day-one internet spray-and-pray. |
| Affected versions | Campcodes Project Management System 1.0 is the only affected version explicitly published in CNA/NVD records. |
| Fixed version | No authoritative fixed release found in Campcodes or CNA references. Treat this as vendor patch unavailable / not disclosed unless your own source diff proves otherwise. |
| Exposure and scanning data | No reliable public census (GreyNoise, Censys, or vendor advisory telemetry) was found for this specific product/CVE in the reviewed sources. My inference: exposure is likely small and manually discoverable rather than mass-fingerprinted. |
| Disclosure timeline | Disclosed 2025-01-03 in CNA timeline; NVD published 2025-01-04 and last modified 2025-01-10. |
| Reporter | Reported by John Correche / John Alan Correche via VulDB references attached to the CNA record. |
noisgate verdict.
The single most important severity brake is that exploitation requires authenticated remote access to a niche PHP application, which makes this a post-foothold path rather than broad initial access. I kept it in MEDIUM because the public PoC is straightforward and, on weak PHP deployments, the bug can become genuine web-shell execution.
Why this verdict
- Downward pressure: requires valid app auth.
PR:Lis not a paper detail here; it implies stolen credentials, session theft, or another bug first, which makes this a post-initial-access issue. - Downward pressure: narrow deployment population. Campcodes is a downloadable PHP/MySQL project for small deployments and educational use, not a high-density enterprise platform with broad managed exposure.
- Upward pressure: file upload can become code execution. The PoC is not theoretical; it shows a working multipart upload of a PHP payload into a web path, which is exactly how web shells land.
- Upward pressure: public weaponization exists. A public GitHub PoC lowers attacker effort and raises reliability once someone already has a session.
- Downward pressure: no exploitation evidence and very low EPSS. No KEV entry, no credible campaign reporting, and low EPSS all argue against emergency treatment across a 10,000-host estate.
Why not higher?
It is not HIGH because the attacker does not get to start from the open internet unauthenticated. Requiring a valid application session, plus the likely small and uneven deployment footprint of this software, compounds the friction hard enough that this is not a broad enterprise fire drill.
Why not lower?
It is not LOW because the technical consequence is more serious than the CVSS sub-scores imply when PHP execution is enabled in the upload path. A real public PoC exists, and once an attacker has app access, exploitation is simple enough to produce a durable web shell.
What to do — in priority order.
- Block script execution in upload paths — Disable PHP execution under the application's
images/and other writable directories using Apache/Nginx/PHP-FPM policy. For a MEDIUM noisgate verdict there is no mitigation SLA, but this is the highest-value hardening step and should go into the next routine web-tier change before the 365-day remediation deadline. - Restrict access to the app — Put the Campcodes instance behind VPN, reverse-proxy allowlists, or at minimum strong SSO/MFA where possible, because the exploit chain starts with a valid session. There is no mitigation SLA for MEDIUM; apply in the next normal access-control cycle and definitely before remediation closes.
- Watch for web-shell patterns — Alert on multipart uploads of
.php, double extensions, and direct requests to newly created files under/images/. There is no mitigation SLA for MEDIUM; deploy as standard detective coverage while you schedule remediation. - Constrain the web service account — Run the app with least privilege, isolate the vhost/container, and remove unnecessary shell tools and secrets from the host so a successful upload has less room to pivot. There is no mitigation SLA for MEDIUM; fold this into normal hardening work before the remediation deadline.
- Retire or locally fix unsupported installs — If no vendor-fixed release exists, treat local code remediation or product retirement as the actual fix: add strict extension allowlists, server-side MIME validation, and deny executable uploads. For MEDIUM, there is no mitigation SLA — go straight to the 365-day remediation window.
- A perimeter WAF alone does not solve this well, because the exploit is a normal authenticated multipart upload and can look like expected application behavior.
- Relying on file extension randomization does not help; the vulnerable code renames the file but preserves the attacker-controlled extension.
- Patching only the OS or PHP runtime does not remove the application logic flaw in
update_forms.php.
Crowdsourced verification payload.
Run this on the target web host that serves Campcodes, not from your scanner workstation. Invoke it as sudo bash verify_cve_2025_0213.sh /var/www/html/construction_pms or point it at the application root; it only needs read access to the webroot, but sudo is often required if the files are owned by root or the web user.
#!/usr/bin/env bash
# verify_cve_2025_0213.sh
# Checks Campcodes Project Management System for the vulnerable upload pattern in forms/update_forms.php
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
APP_ROOT="${1:-}"
TARGET_REL="forms/update_forms.php"
if [[ -z "$APP_ROOT" ]]; then
echo "UNKNOWN - usage: $0 /path/to/construction_pms"
exit 2
fi
TARGET="$APP_ROOT/$TARGET_REL"
if [[ ! -e "$TARGET" ]]; then
echo "UNKNOWN - file not found: $TARGET"
exit 2
fi
if [[ ! -r "$TARGET" ]]; then
echo "UNKNOWN - cannot read: $TARGET"
exit 2
fi
content="$(cat "$TARGET")"
has_change_pic2=0
has_move_upload=0
has_images_path=0
has_validation=0
has_php_block=0
printf '%s' "$content" | grep -q "change_pic2" && has_change_pic2=1
printf '%s' "$content" | grep -q "move_uploaded_file" && has_move_upload=1
printf '%s' "$content" | grep -q "\.\./images/" && has_images_path=1
# crude signs of extension/MIME validation or explicit deny rules
printf '%s' "$content" | grep -Eqi "(in_array\s*\(|preg_match\s*\(|mime_content_type\s*\(|finfo_|pathinfo\s*\(|allowed(_|)ext|whitelist|blacklist|application/x-php|php[0-9]?\$|deny)" && has_validation=1
# optional server-side defense check: look for common Apache/Nginx rules near app root
if find "$APP_ROOT" -maxdepth 2 \( -name ".htaccess" -o -name "nginx.conf" -o -name "default.conf" -o -name "*.conf" \) -type f 2>/dev/null | xargs -r grep -Eqi "<FilesMatch.*php|location.*images|deny all|return 403|php_admin_flag engine off|RemoveHandler .*php|SetHandler none"; then
has_php_block=1
fi
if [[ $has_change_pic2 -eq 1 && $has_move_upload -eq 1 && $has_images_path -eq 1 && $has_validation -eq 0 ]]; then
if [[ $has_php_block -eq 1 ]]; then
echo "UNKNOWN - vulnerable code pattern present, but server config appears to block some script execution paths; validate manually"
exit 2
else
echo "VULNERABLE - unrestricted upload pattern detected in $TARGET"
exit 1
fi
fi
if [[ $has_change_pic2 -eq 0 && $has_move_upload -eq 0 ]]; then
echo "PATCHED - vulnerable handler signature not found in $TARGET"
exit 0
fi
if [[ $has_validation -eq 1 ]]; then
echo "PATCHED - upload handler contains signs of validation/hardening; review manually to confirm"
exit 0
fi
echo "UNKNOWN - inconclusive result; review $TARGET manually"
exit 2
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.