Using Zeek to detect exploitation of Citrix CVE-2019-19781

Using Zeek to detect exploitation of Citrix CVE-2019-19781

Using the tool

Zeek, formally known as bro, is a high-level packet analysis program. It originally began development in the 1990s and has a long history. It does not directly intercept or modify traffic, rather it passively observes it and creates high-level network logs. It can be used in conjunction with a SIEM to allow quick analysis. It can operate in realtime to create logs of a currently active system, or as a post-mortem analysis tool of a packet capture. This tool can also operate with pf_ring to increase network capture performance due to a well-supported plugin.

Creating a script

While zeek does have some good documentation online, it is definitely lacking in any sort of tutorial-based content for beginners. This is especially true for anyone who wants to try their hand at using zeek scripting language to create a custom plugin.

A simplified understanding of what a signature detection based zeek plugin has to do is:

  1. Define the log format and alert types for the plugin
  2. Define the signatures for detection
  3. Initialize zeek to include a new LogStream
  4. Create an event listener that matches your packets protocol

CVE-2019-19781 signatures

Between the patterns defined in this yara rule and the us-cert alert a pattern can be constructed. In this case, the following regex patterns will be used to match malicious URIs:

.*\/\.\.\/vpns\/.*
.*\/vpns\/.*
.*\/vpns\/cfg\/smb.conf
.*\/vpns\/portal\/scripts\/newbm\.pl.*
.*\/vpns\/portal\/scripts\/rmbm\.pl.*
.*\/vpns\/portal\/scripts\/picktheme\.pl.*

Importing necessary protocols and defining the module

Here we define the module as NETSCALARD, although a CVE number would have been just as appropriate.

@load base/protocols/http
@load base/frameworks/notice

module NETSCALARD;

Defining log file

To define the log file there needs to be a log identifier, in this case a NETSCALARD::LOG is used, and a record entry for how the data should be recorded into the file.

export {
    ## The logging stream identifier.
    redef enum Log::ID += { LOG };

    ## The record type which contains column fields of the certificate log.
    type Info: record {
        src:         addr   &log;
        dst:         addr   &log;
        ## Timestamp when this record is written.
        ts:          time   &log;
        ## URI of request
        URI:         string &log;
    };
    # cont.
}

Defining notice type

Zeek allows plugins to define a different Notice type that can be used when generating emails. There are a lot of pre-defined notices that can be used and they are indexed here.

export {
    # cont.
    redef enum Notice::Type += {
        Netscalar_Attack,
    };
    # cont.
}

Defining signatures

Zeek provides a pattern type that can be used to quickly define multiple regex patterns. The language also has some pattern specific operations such as in which can check if a pattern is found in a string.

export {
    # cont.
    const match_bad_signatures =
          /.*\.\.\/vpns\/.*/
        | /.*vpns\/cfg\/smb.conf/
        | /.*vpns\/portal\/scripts\/newbm\.pl/
        | /.*vpns\/portal\/scripts\/rmbm\.pl/
        | /.*vpns\/portal\/scripts\/picktheme\.pl/ &redef;
}

Initializing Zeek

When initializing zeek there are a few different methods of recording events. In this case a dedicated log file was chosen. To create this log stream based on the log specifications Log::create_stream can be used.

event zeek_init() &priority=3 {
    Log::create_stream(NETSCALARD::LOG, [$columns=Info, $path="netscalard-attacks"]);
}

Creating an event listener

The netscalard exploit uses a POST request to one of the defined bad URIs. To effectively match this pattern and not cause encumberance with checking every request the code will quickly return from packets that are not a POST request, or that don’t meet one of the defined signatures. The remaining packets, the malicious packets, can be recorded. To record the attack the code creates a notice that will be placed in notice.log as well as a dedicated log entry for the netscalard-attacks log file.

event http_request(c: connection, method: string, original_URI: string,
        unescaped_URI: string, version: string) &priority=3 {

    if (!( method == "POST" ))
        return;

    if (!( match_bad_signatures in unescaped_URI ))
        return;

    NOTICE([
        $note=Netscalar_Attack,
        $msg=fmt("Netscalar attack attempt made by (%s) against (%s)", c$id$orig_h, c$id$resp_h),
        $sub=cat(c$id$orig_h,c$id$resp_h,unescaped_URI)
    ]);

    Log::write(
        NETSCALARD::LOG,
        Info(
            $src=c$id$orig_h,
            $dst=c$id$resp_h,
            $ts=network_time(),
            $URI=unescaped_URI
        )
    );
}

Output

After running this script against the local interface for testing with the following command:

sudo zeek -C -i lo ../detect-netscalard.zeek

There are some log files generated. Once a malicious packet has been detected, in this case triggered from a curl command, then a new notice.log file and netscalard-attacks.log will be generated. The notices file can be fed into zeek-cut to extract the important information.

> $ cat notice.log | zeek-cut -d note msg
NETSCALARD::Netscalar_Attack    Netscalar attack attempt made by (127.0.0.1) against (127.0.0.1)
NETSCALARD::Netscalar_Attack    Netscalar attack attempt made by (127.0.0.1) against (127.0.0.1)
NETSCALARD::Netscalar_Attack    Netscalar attack attempt made by (127.0.0.1) against (127.0.0.1)
NETSCALARD::Netscalar_Attack    Netscalar attack attempt made by (127.0.0.1) against (127.0.0.1)
NETSCALARD::Netscalar_Attack    Netscalar attack attempt made by (127.0.0.1) against (127.0.0.1)
> $ cat netscalard-attacks.log
#fields src dst ts  URI
#types  addr    addr    time    string
127.0.0.1   127.0.0.1   1593933273.086046   /vpns/portal/scripts/newbm.pl
127.0.0.1   127.0.0.1   1593933273.486067   /vpns/portal/scripts/newbm.pl
127.0.0.1   127.0.0.1   1593933273.799568   /vpns/portal/scripts/newbm.pl
127.0.0.1   127.0.0.1   1593933274.093156   /vpns/portal/scripts/newbm.pl
127.0.0.1   127.0.0.1   1593933274.371653   /vpns/portal/scripts/newbm.pl
#close  2020-07-05-17-14-46

Using this plugin post-mortem analysis can also be performed. An example command for this is shown below:

sudo zeek ../detect-netscalard.zeek -r packetcapture.pcap

More Blogs

May 31, 2021

Upgrading from AppLocker to Windows Defender Application Control (WDAC)

Windows Defender Application Control (WDAC), formerly known as Device Guard, is a Microsoft Windows secure feature that restricts executable code, including scripts run by enlightened Windows script hosts, to those that conform to the device code integrity policy. WDAC prevents the execution, loading and running of unwanted or malicious code, drivers and scripts. WDAC also… Continue reading Upgrading from AppLocker to Windows Defender Application Control (WDAC)

Read More
cyber security companies | penetration testing | managed security service provider | cyber security consultant
June 22, 2021

Bypassing LSA Protection (aka Protected Process Light) without Mimikatz on Windows 10

Starting with Windows 8.1 (and Server 2012 R2) Microsoft introduced a feature termed LSA Protection. This feature is based on the Protected Process Light (PPL) technology which is a defense-in-depth security feature that is designed to “prevent non-administrative non-PPL processes from accessing or tampering with code and data in a PPL process via open process… Continue reading Bypassing LSA Protection (aka Protected Process Light) without Mimikatz on Windows 10

Read More
cyber security companies | penetration testing | managed security service provider | cyber security consultant
July 6, 2020

Bypassing CrowdStrike Endpoint Detection and Response

In a recent engagement I had to compromise a hardened desktop running CrowdStrike and Symantec Endpoint Protection. The initial code execution method was my reliable favourite MSBuild (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe) which could be leveraged to execute C# code as an inline task. Initially I wrote a very basic loader that used a bruteforce decryption algorithm to run… Continue reading Bypassing CrowdStrike Endpoint Detection and Response

Read More