Patching BADLOCK with Ansible

April 12, 2016 by Bill Nottingham

Ansible-Lock-Blog.png

If you've been following recent security news, you may have heard of the Badlock vulnerability in the protocols used by the Microsoft Windows Active Directory infrastructure. This vulnerability could lead to a man-in-the-middle attacker intercepting traffic between a client and the Active Directory server, and then impersonating the client, gaining unauthorized access to resources.

 block-bug.png

More information can be found at http://badlock.org/ and the Red Hat Knowledgebase.


Thanks to Ansible, however, patching your systems doesn't have to be complicated.

Here’s a sample playbook for Red Hat/Fedora/CentOS and Debian/Ubuntu systems

- hosts: all
  gather_facts: true
  become_method: sudo
  become_user: root
  vars:
    service_name:
      'Debian': 'smbd'
      'RedHat': 'smb'

  tasks:
    - name: check samba version
      shell: dpkg -l | grep -q samba
      when: ansible_os_family == 'Debian'
      register: samba_installed
      ignore_errors: True

    - name: update samba from apt if installed
      apt:
        name: samba
        state: latest
        update_cache: yes
      when: ansible_os_family == 'Debian' and samba_installed.rc == 0
      notify: restart_samba

    - name: check samba version
      shell: rpm -q samba
      when: ansible_os_family == 'RedHat'
      register: samba_installed
      ignore_errors: True

    - name: update samba from yum if installed
      yum:
        name: samba
        state: latest
        update_cache: yes
      when: ansible_os_family == 'RedHat' and samba_installed.rc == 0
      notify: restart_samba

  handlers:
    - name: restart_samba
      service:
        name: "{{ service_name[ansible_os_family] }}"
        state: restarted

Note that this version merely installs the latest version of Samba from your vendor. If you know the versions that are vulnerable for your OS or the versions where the fix has been applied, you can create a playbook that tests to make sure you have a correct version. Here’s an example for Red Hat Enterprise Linux systems. (Note: if you’re on a particular EUS or ELS subscription, you may need to adjust the version check. Check the Red Hat Knowledgebase for details.)

- hosts: all
  gather_facts: true
  become_method: sudo
  become_user: root
  vars:
    vulnerable_releases:
      '5': '3.0.33-3.40.el5_10'
      '6': '3.6.23-25.el6_7'
      '7': '4.2.3-12.el7_2'
    vulnerable_3x:
      '5': '3.6.23-9.el5_11'
    vulnerable_4:
      '6': '4.0.0-68.el6_7.rc4'

  tasks:
    # Base Samba package
    - name: check for samba version
      shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba.{{ ansible_architecture }}
      register: samba_version
      ignore_errors: true

    - block:
      - name: check for vulnerable versions
        debug:
          msg: "Samba version {{ samba_version.stdout }} is vulnerable."
        when: samba_version.stdout|version_compare(vulnerable_releases[ansible_distribution_major_version], '<=')
        register: is_vuln
      
      - name: update samba from yum if vulnerable
        yum: 
          name: samba
          state: latest
          update_cache: yes
        when: not is_vuln|skipped
        notify: restart_samba
        register: installed
      
      - name: check for samba version
        shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba.{{ ansible_architecture }}
        register: samba_new_version
        when: not is_vuln|skipped
        
      - name: check that we are no longer vulnerable
        debug:
          msg: "Samba version {{ samba_new_version.stdout }} is still vulnerable!"
        when: not is_vuln|skipped
        failed_when: samba_new_version.stdout|version_compare(vulnerable_releases[ansible_distribution_major_version], '<=')

      when: samba_version.rc == 0

  
    # Samba 3x package (RHEL 5)
    - name: check for samba3x version
      shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba3x.{{ ansible_architecture }}
      register: samba3x_version
      ignore_errors: True

    - block:
      - name: check for vulnerable versions
        debug:
          msg: "Samba3x version {{ samba3x_version.stdout }} is vulnerable."
        when: samba3x_version.stdout|version_compare(vulnerable_3x[ansible_distribution_major_version], '<=')
        register: is_vuln
      
      - name: update samba3x from yum if vulnerable
        yum: 
          name: samba3x
          state: latest
          update_cache: yes
        when: not is_vuln|skipped
        notify: restart_samba
        register: installed
      
      - name: check for samba3x version
        shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba3x.{{ ansible_architecture }}
        register: samba3x_new_version
        when: not is_vuln|skipped
        
      - name: check that we are no longer vulnerable
        debug:
          msg: "Samba3x version {{ samba3x_new_version.stdout }} is still vulnerable!"
        when: not is_vuln|skipped
        failed_when: samba3x_new_version.stdout|version_compare(vulnerable_3x[ansible_distribution_major_version], '<=')

      when: samba3x_version.rc == 0
  
    # Samba 4x package (RHEL 6)
    - name: check for samba4 version
      shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba4.{{ ansible_architecture }}
      register: samba4_version
      ignore_errors: True

    - block:
      - name: check for vulnerable versions
        debug:
          msg: "Samba4 version {{ samba4_version.stdout }} is vulnerable."
        when: samba4_version.stdout|version_compare(vulnerable_4[ansible_distribution_major_version], '<=')
        register: is_vuln
      
      - name: update samba4 from yum if vulnerable
        yum: 
          name: samba4
          state: latest
          update_cache: yes
        when: not is_vuln|skipped
        notify: restart_samba
        register: installed
      
      - name: check for samba4 version
        shell: rpm -q --qf "%{VERSION}-%{RELEASE}" samba4.{{ ansible_architecture }}
        register: samba4_new_version
        when: not is_vuln|skipped
        
      - name: check that we are no longer vulnerable
        debug:
          msg: "Samba4 version {{ samba4_new_version.stdout }} is still vulnerable!"
        when: not is_vuln|skipped
        failed_when: samba4_new_version.stdout|version_compare(vulnerable_4[ansible_distribution_major_version], '<=')

      when: samba4_version.rc == 0
        
  handlers:
    - name: restart_samba
      service:
        name: "{{ service_name[ansible_os_family] }}"
        state: restarted

Note that if you have a Red Hat Satellite server in your environment, you’ll need to ensure that your nightly package sync has run and has the latest Samba packages.

But Ansible isn't just for patching your Linux machines. As noted above, this is a cross-platform protocol issue in the protocols used for Active Directory - that means you may need to patch Windows systems as well. With Ansible, that's just a simple playbook as well. In this case, this playbook uses the 'win_reboot' role from Ansible Galaxy.

- hosts: all
  gather_facts: true

  pre_tasks:
    - name: apply security updates
      win_updates:
        category_names: [u'SecurityUpdates',u'CriticalUpdates']
        state: installed
      register: updated 

  roles:
    - { role: trondhindenes.win_reboot, when: "updated.reboot_required" }

These playbooks can be found at https://github.com/ansible/ansible-blog-examples.

Want to remediate BADLOCK, but haven't used Ansible before?
Getting started is easy

 

 

Share:

Topics:
Configuration Management, Ansible, Red Hat, Linux, Security and Compliance


 

Bill Nottingham

Bill Nottingham is the Director of Product at Ansible. He came to Ansible from Red Hat, where he spent 15+ years building and architecting Red Hat’s Linux products. His days are spent chatting with users and customers about Ansible and Tower. He can be found on twitter at @bill_nottingham, and occasionally doing a very poor impersonation of a soccer player.


rss-icon  RSS Feed

Ansible Tower by Red Hat
Ansible In-Depth Whitepaper
Ansible Tower by Red Hat
Learn About Ansible Tower