Protecting your servers against ImageTragick (CVE-2016-3714) and CVE-2016-5118 using Ansible

On May 3rd, details were published about a vulnerability in ImageMagick (CVE-2016-3714), allowing remote code execution if you process user submitted images. Exploits for this vulnerability are being used in the wild.

The following ansible playbook may be used to apply the policy file mitigation discussed on that website. If the server(s) you wish to protect has a policy.xml file in a different location, be sure to modify the with_items list of the first task.

Update 2nd of June: on May 29th, another vulnerability was disclosed regarding ImageMagick. This vulnerability was assigned CVE-2016-5118. It is possible to execute shell commands by using a pipe in the file open syntax. The playbook below has been modified to protect agains this vulnerability as well, with special thanks to Henk-Jan Agteresch.

Note: Updated packages have been released that fix this vulnerability for Ubuntu and Debian. The updated packages make the policy.xml file change unnecessary (but it wont hurt either).

---
- hosts: all
  become: true
  gather_facts: false

  tasks:
    - name: find out what the default policy.xml location is
      command: convert -list policy
      register: convert_policy
      failed_when: false
      changed_when: false

    - set_fact:
        default_convert_policy: "{{ convert_policy.stdout_lines[1]|regex_replace(\"Path: (.*)\", \"\\1\")}}"
      when: "'Path' in convert_policy.stdout"

    - name: check which policy.xml exists
      stat:
        path: "{{ item }}"
      with_items:
        - "{{ default_convert_policy|default(\"/etc/ImageMagick/policy.xml\") }}"
        - /etc/ImageMagick-6/policy.xml
        - /etc/ImageMagick-7/policy.xml
        - /usr/local/etc/ImageMagick/policy.xml
        - /usr/local/etc/ImageMagick-6/policy.xml
        - /usr/local/etc/ImageMagick-7/policy.xml
      register: policy_xml

    - name: for every policy.xml that exists ensure lines are in the config
      lineinfile:
        dest: "{{ item.0.item }}"
        insertbefore: "</policymap>"
        line: "{{ item.1 }}"
      with_nested:
        - "{{ policy_xml.results }}"
        - ['  <policy domain="coder" rights="none" pattern="EPHEMERAL" />',
           '  <policy domain="coder" rights="none" pattern="URL" />',
           '  <policy domain="coder" rights="none" pattern="HTTPS" />',
           '  <policy domain="coder" rights="none" pattern="MVG" />',
           '  <policy domain="coder" rights="none" pattern="MSL" />',
           '  <policy domain="path" rights="none" pattern="|*" />',
          ]
      when: item.0.stat.exists

To execute the playbook, save it in a file called imagetragick.yml and execute it using ansible-playbook:

$ ansible-playbook imagetragick.yml