Metasploit Module: AF_PACKET packet_set_ring Privilege Escalation
Type: exploit
Path: modules/exploits/linux/local/af_packet_packet_set_ring_priv_esc.rb
Disclosure date: 2017-03-29
References: EDB-41994, CVE-2017-7308, BID-97234, URL-https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html, URL-https://www.coresecurity.com/blog/solving-post-exploitation-issue-cve-2017-7308, URL-https://people.canonical.com/~ubuntu-security/cve/2017/CVE-2017-7308.html, URL-https://github.com/xairy/kernel-exploits/blob/master/CVE-2017-7308/poc.c, URL-https://github.com/bcoles/kernel-exploits/blob/cve-2017-7308/CVE-2017-7308/poc.c

Description:
This module exploits a heap-out-of-bounds write in the packet_set_ring
          function in net/packet/af_packet.c (AF_PACKET) in the Linux kernel
          to execute code as root (CVE-2017-7308).

          The bug was initially introduced in 2011 and patched in version 4.10.6,
          potentially affecting a large number of kernels; however this exploit
          targets only systems using Ubuntu Xenial kernels 4.8.0 < 4.8.0-46,
          including Linux distros based on Ubuntu Xenial, such as Linux Mint.

          The target system must have unprivileged user namespaces enabled and
          two or more CPU cores.

          Bypasses for SMEP, SMAP and KASLR are included. Failed exploitation
          may crash the kernel.

          This module has been tested successfully on Linux Mint 18 (x86_64)
          with kernel versions:

          4.8.0-34-generic;
          4.8.0-36-generic;
          4.8.0-39-generic;
          4.8.0-41-generic;
          4.8.0-42-generic;
          4.8.0-44-generic;
          4.8.0-45-generic.

Check method (fingerprinting):
version = kernel_release
    unless version =~ /^4\.8\.0-(34|36|39|41|42|44|45)-generic/
      vprint_error "Linux kernel version #{version} is not vulnerable"
      return CheckCode::Safe("Kernel version #{version} is not vulnerable")
    end
    vprint_good "Linux kernel version #{version} is vulnerable"

    arch = kernel_hardware
    unless arch.include? 'x86_64'
      vprint_error "System architecture #{arch} is not supported"
      return CheckCode::Safe("System architecture #{arch} is not supported")
    end
    vprint_good "System architecture #{arch} is supported"

    cores = get_cpu_info[:cores].to_i
    min_required_cores = 2
    unless cores >= min_required_cores
      vprint_error "System has less than #{min_required_cores} CPU cores"
      return CheckCode::Safe('System has insufficient CPU cores')
    end
    vprint_good "System has #{cores} CPU cores"

    config = kernel_config
    if config.nil?
      vprint_error 'Could not retrieve kernel config'
      return CheckCode::Unknown('Could not retrieve kernel config')
    end

    unless config.include? 'CONFIG_USER_NS=y'
      vprint_error 'Kernel config does not include CONFIG_USER_NS'
      return CheckCode::Safe('Kernel config does not include CONFIG_USER_NS')
    end
    vprint_good 'Kernel config has CONFIG_USER_NS enabled'

    unless userns_enabled?
      vprint_error 'Unprivileged user namespaces are not permitted'
      return CheckCode::Safe('Unprivileged user namespaces are not permitted')
    end