Like a pickpocket who needs your badge, your building key, and eight hours alone with your filing cabinet
CVE-2026-61797 is a time-based blind SQL injection in the GLPI PDF Plugin (versions ≤ 4.1.2). The flaw lives in /marketplace/pdf/front/preference.form.php, where user-supplied array *keys* from the item POST parameter are concatenated directly into SQL INSERT statements hitting the glpi_plugin_pdf_preferences table — no parameterization, no escaping. Any authenticated GLPI user, even at the lowest privilege tier, can inject SLEEP()-based payloads to infer database contents one bit at a time. The fix shipped in PDF Plugin 4.1.3, released the same day as disclosure on September 14, 2026. Researcher Javier Medina of ITRESIT Labs coordinated the disclosure responsibly and published a sqlmap-ready PoC at itres-labs/CVE-2026-61797.
The GHSA advisory tags this at 6.1, and Sploitus indexes it at 5.9. Both figures feel slightly generous for real-world risk. Yes, it is a network-reachable SQL injection — the classic nightmare class — but three compounding friction factors blunt the impact: (1) the attacker must already hold valid GLPI credentials, (2) a fresh CSRF token is required per request (modern GLPI enforces single-use tokens), and (3) time-based blind extraction is agonizingly slow — dumping a meaningful credential table can take hours of sustained, pattern-rich traffic that any decent WAF or query-latency monitor should flag. The PDF plugin is also *optional*; not every GLPI deployment has it installed or activated. The GitHub repo for the plugin has just 7 stars. Taken together, this is a real vulnerability with a credible PoC, but it sits comfortably in MEDIUM territory rather than the HIGH range its SQL-injection lineage might suggest.
6 steps from start to impact.
Obtain low-privilege GLPI credentials
- Network access to the GLPI web interface
- Valid GLPI user credentials (any privilege tier)
- Requires prior credential compromise or social engineering
- Self-registration is disabled by default in GLPI ≥ 10.x
- MFA plugins exist and would block credential-only attacks
Confirm PDF plugin is installed and active
/marketplace/pdf/front/preference.form.php. If the plugin is absent or deactivated, the endpoint returns a 404 or GLPI error page. The PDF plugin is an *optional* community plugin — not bundled with GLPI core. An administrator must install and explicitly activate it.- GLPI PDF plugin (pluginsGLPI/pdf) version ≤ 4.1.2 installed and active
- Plugin is optional — only a subset of GLPI deployments install it
- Plugin must be activated by an admin, not just present on disk
- GLPI Cloud instances may receive auto-updates that already patched this
Harvest CSRF token and prepare injection payload
_glpi_csrf_token, and crafts a POST body with item[0*]=1 where the asterisk marks the sqlmap injection point. Modern GLPI rotates CSRF tokens per request, so the attacker's tooling must programmatically fetch a fresh token before each injection attempt. The PoC documents this workflow for sqlmap's --csrf-url and --csrf-token flags.- Active authenticated GLPI session
- Ability to parse CSRF token from the preference form HTML
- Single-use CSRF tokens mean each injection request requires a full round-trip to fetch a new token — doubling request volume
- Automated CSRF handling adds implementation complexity beyond basic sqlmap usage
Execute time-based blind SQL injection via sqlmap
sqlmap -r glpi.sqli --csrf-url=<URL> --csrf-token=_glpi_csrf_token --technique=T --level=5 --risk=1 --batch. Sqlmap injects SLEEP(N) into the array key, measuring response-time deltas to infer Boolean conditions bit by bit. Each character of exfiltrated data requires ~7-8 requests. Dumping a single row of glpi_users can take several minutes; an entire credential table with hundreds of users takes hours of sustained traffic.- sqlmap or equivalent tool configured for CSRF token refresh
- Stable, low-jitter network connection for accurate timing inference
- Time-based blind is the *slowest* SQLi technique — hours for meaningful exfiltration
- High request volume produces obvious anomalies in access logs and DB slow-query logs
- Network jitter, load balancers, and connection pooling can corrupt timing signals
SLEEP() calls; WAF SQL injection signatures (OWASP CRS rule 942100+); response-time anomaly detection on the endpoint.Exfiltrate sensitive data from the GLPI database
glpi_users (password hashes, API tokens, email addresses), glpi_configs (SMTP credentials, LDAP bind DN and password), and glpi_computers/glpi_networkequipments (full asset inventory). Stored LDAP bind passwords in glpi_configs could enable direct AD authentication. Asset inventory data accelerates lateral movement planning.- Successful injection established in step 4
- Hours of uninterrupted exfiltration time
- Read-only access — no direct code execution, file write, or OS command injection via this vector
- Password hashes in
glpi_usersuse bcrypt by default in recent GLPI versions, requiring offline cracking - LDAP bind passwords may be encrypted at rest depending on GLPI version and configuration
Leverage exfiltrated credentials for lateral movement
- Recovered plaintext or cracked credentials from step 5
- Credential reuse across services in the environment
- Requires successful offline cracking or plaintext credential storage — not guaranteed
- Network segmentation and MFA on downstream services limit lateral movement
- This is a chained, multi-step scenario beyond the immediate vulnerability
/marketplace/pdf/front/preference.form.php for SQL injection signatures in array-key parameters. OWASP CRS rules 942100-942999 cover common SQLi patterns including SLEEP() and BENCHMARK(). This catches automated sqlmap exploitation but may not stop a manually crafted bypass. Deploy within the 365-day noisgate remediation SLA.slow_query_log = 1 with long_query_time = 2 in MySQL/MariaDB and create a SIEM alert for queries containing SLEEP(), BENCHMARK(), or WAITFOR DELAY. This provides detection-in-depth for time-based blind exploitation in progress, enabling incident response before meaningful data exfiltration completes. Deploy within the 365-day noisgate remediation SLA.- Reducing GLPI user role permissions — the injection works at the *lowest* GLPI privilege tier. GLPI's internal RBAC does not restrict access to the vulnerable
preference.form.phpendpoint for any authenticated user, regardless of profile. - PHP-level input sanitization (e.g.,
mysql_real_escape_string) — the vulnerability is in array *key* handling, not value handling. Most input-validation libraries and frameworks sanitize POST *values* but pass array keys through unescaped. A framework-level fix requires parameterized queries, not input filtering. - Network segmentation between the web server and database — the injection executes through the GLPI application's existing, legitimate database connection. The attacker never opens a direct connection to MySQL; they piggyback on the app's own
$DB->doQuery()call. Segmenting the DB from the internet does not help.
The supporting signals.
| In-the-wild exploitation | No evidence of active exploitation as of October 2026. Not listed in CISA KEV. No GreyNoise, Shadowserver, or threat-intelligence tags observed for this CVE. GLPI has a history of exploitation (CVE-2022-35914 was mass-exploited per VulnCheck), but this authenticated plugin flaw is far less attractive to scanners. |
|---|---|
| Proof of Concept | Public, weaponized PoC at itres-labs/CVE-2026-61797 — includes a sqlmap-ready request file, documented CSRF-token handling, and step-by-step exploitation guide. Also indexed on Sploitus. The PoC lowers the skill barrier to anyone comfortable running sqlmap. |
| EPSS score | Not yet scored — CVE was disclosed 2026-09-14; FIRST's EPSS model typically lags 30-60 days for new CVEs. Expect a low-to-moderate probability score given the authentication prerequisite. |
| KEV status | Not listed in CISA Known Exploited Vulnerabilities catalog. Unlikely to be added absent evidence of active exploitation campaigns. |
| CVSS (CNA/GHSA) | GHSA reports 6.1/10; Sploitus indexes at 5.9/10. No NVD score published. Reasonable estimated vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N (= 6.5) — the GHSA's 6.1 likely models CSRF as UI:R. Confidentiality-only impact (no integrity/availability) reflects the read-only nature of blind SQLi. |
| Affected versions | GLPI PDF Plugin ≤ 4.1.2 (tested on 4.1.2). Earlier 4.x branches likely affected if the preference.form.php code path exists. Pre-4.x branches untested. |
| Fixed version | GLPI PDF Plugin 4.1.3 — released 2026-09-14 (same-day patch). GLPI Network Cloud instances (Public and Private) may have received automatic updates. |
| Internet exposure | ~15,000 internet-facing GLPI instances per Censys; ~7,500 per Shodan. Per VulnCheck, ~10% of internet-facing GLPI servers remain unpatched for *older* CVEs. The subset with the PDF plugin active and vulnerable is unknown but substantially smaller than the total GLPI footprint. |
| Disclosure timeline | 2026-09-14: Coordinated disclosure by Javier Medina (ITRESIT Labs), patch release, and PoC publication — all same day. Responsible, compressed timeline. |
| Researcher | Javier Medina of ITRESIT Labs — published detailed technical analysis and sqlmap-ready PoC with coordinated vendor notification. |
Sources.
Why this verdict
- Authentication barrier is a real gate: This is not pre-auth. The attacker must possess valid GLPI credentials *before* reaching the vulnerable endpoint. In standalone GLPI deployments, accounts are admin-provisioned. In LDAP-synced environments the user pool is larger, but the attacker still needs to compromise at least one account first — a separate, non-trivial attack step that compounds friction.
- Time-based blind technique is operationally punishing: Each character of exfiltrated data requires ~8 HTTP round-trips with timing analysis. Dumping a 500-row
glpi_userstable realistically takes 4-8+ hours of sustained, anomalous traffic. Any WAF with OWASP CRS rules, any MySQL slow-query alert onSLEEP(), or even a basic request-rate monitor should detect this. The technique is theoretically sound but practically noisy. - Optional plugin narrows the vulnerable population significantly: The PDF plugin is not part of GLPI core. It must be separately installed and activated. The GitHub repo has 7 stars and 15 forks — this is a niche component. A large fraction of the ~15K internet-facing GLPI instances will not have it.
- CSRF token handling doubles attacker overhead: Modern GLPI issues single-use CSRF tokens. Every injection request requires a preceding GET to fetch a fresh token, doubling request volume and further slowing exploitation. Script-kiddie-level sqlmap invocations without
--csrf-urlhandling will simply fail. - Role multiplier: GLPI is a line-of-business IT asset management and helpdesk platform. It is not a canonical high-value-role component — it is not an identity provider, domain controller, hypervisor, CI/CD system, CA, PAM vault, backup target, kernel-mode agent, or network edge appliance. (a) Low-value role: Dev/test GLPI instances — minimal blast radius, limited data. (b) Typical role: Production GLPI for an IT ops team — contains asset inventory, helpdesk tickets, user accounts. A database compromise here yields operational data and potentially LDAP bind credentials stored in
glpi_configs. Blast radius is host-to-tenant-level, not fleet or domain. (c) High-value role: GLPI integrated with AD/LDAP storing bind credentials for auto-discovery — worst case is credential recovery enabling lateral movement, which requires a *separate chained attack*. GLPI is not canonically deployed in a high-value role (it is not the IdP itself, nor the DC, nor the network edge). The blast radius does not reach domain/fleet/supply-chain scale from this vulnerability alone. No HIGH floor is triggered.
Why not higher?
A HIGH rating would require pre-auth access, direct code execution, or a canonical high-value-role deployment. This vulnerability requires authentication, produces only *read* access to the database (no RCE, no file write, no OS command injection), and targets an optional plugin on a line-of-business application. While the database *could* contain integration credentials, exploiting those requires a separate, chained attack. The time-based blind technique is inherently slow and detectable. The authentication + CSRF + optional-plugin + slow-exfil chain represents enough compounding friction to keep this firmly below HIGH.
Why not lower?
A LOW rating would understate the risk because a public, sqlmap-ready PoC exists and the SQL injection is *real* — it reaches glpi_users, glpi_configs, and asset tables containing potentially sensitive data. Approximately 15,000 GLPI instances are internet-facing, and GLPI has a documented history of exploitation (CVE-2022-35914 was mass-exploited). Many GLPI deployments sync users from Active Directory, meaning low-privilege accounts are abundant. The authentication barrier reduces but does not eliminate the threat.
Crowdsourced verification payload.
Run this script on the GLPI application server (or any host with filesystem access to the GLPI web root). Invoke with: sudo bash check_cve_2026_61797.sh /var/www/html/glpi (pass the GLPI installation path as the first argument). Requires read access to the plugin directory. Outputs VULNERABLE, PATCHED, or UNKNOWN with exit codes 1, 0, 2 respectively.
#!/usr/bin/env bash
# check_cve_2026_61797.sh
# Detects CVE-2026-61797: GLPI PDF Plugin blind SQLi in preference.form.php
# Usage: bash check_cve_2026_61797.sh /path/to/glpi
# Exit: 0=PATCHED 1=VULNERABLE 2=UNKNOWN
set -euo pipefail
GLPI_ROOT="${1:-/var/www/html/glpi}"
# Locate the PDF plugin in either marketplace or plugins directory
for DIR in "$GLPI_ROOT/marketplace/pdf" "$GLPI_ROOT/plugins/pdf"; do
if [[ -d "$DIR" ]]; then
PLUGIN_DIR="$DIR"
break
fi
done
if [[ -z "${PLUGIN_DIR:-}" ]]; then
echo "UNKNOWN — GLPI PDF plugin not found in $GLPI_ROOT/marketplace/pdf or $GLPI_ROOT/plugins/pdf"
echo " (Plugin may not be installed — if so, this CVE does not apply.)"
exit 2
fi
SETUP="$PLUGIN_DIR/setup.php"
if [[ ! -f "$SETUP" ]]; then
echo "UNKNOWN — setup.php not found at $SETUP"
exit 2
fi
# Extract PLUGIN_PDF_VERSION from setup.php
VER=$(grep -oP "define\\s*\\(\\s*['\"]PLUGIN_PDF_VERSION['\"]\\s*,\\s*['\"]\\K[0-9]+\\.[0-9]+\\.[0-9]+" "$SETUP" 2>/dev/null || true)
if [[ -z "$VER" ]]; then
echo "UNKNOWN — could not parse PLUGIN_PDF_VERSION from $SETUP"
exit 2
fi
echo "Detected GLPI PDF Plugin version: $VER"
# Parse semver components
IFS='.' read -r MAJOR MINOR PATCH <<< "$VER"
MAJOR=${MAJOR:-0}; MINOR=${MINOR:-0}; PATCH=${PATCH:-0}
# Vulnerable: 4.1.0 through 4.1.2
# Fixed: 4.1.3+
# Pre-4.1.x: unknown (untested branch)
if (( MAJOR > 4 )) || (( MAJOR == 4 && MINOR > 1 )); then
echo "PATCHED — version $VER is newer than the affected 4.1.x branch"
exit 0
elif (( MAJOR == 4 && MINOR == 1 && PATCH >= 3 )); then
echo "PATCHED — version $VER contains the fix for CVE-2026-61797"
exit 0
elif (( MAJOR == 4 && MINOR == 1 && PATCH <= 2 )); then
# Double-check: look for the vulnerable code pattern in preference.form.php
PREF="$PLUGIN_DIR/front/preference.form.php"
if [[ -f "$PREF" ]] && grep -qP 'foreach.*\$_POST.*item.*\$key.*doQuery' "$PREF" 2>/dev/null; then
echo "VULNERABLE — PDF Plugin $VER contains the unsanitized array-key SQL injection in preference.form.php"
else
echo "VULNERABLE — PDF Plugin $VER is in the affected version range (code-pattern check inconclusive)"
fi
exit 1
elif (( MAJOR == 4 && MINOR < 1 )); then
echo "UNKNOWN — version $VER predates the tested 4.1.x branch; manual review required"
exit 2
elif (( MAJOR < 4 )); then
echo "UNKNOWN — version $VER predates the tested branch; manual review required"
exit 2
fi
echo "UNKNOWN — could not determine status for version $VER"
exit 2