Lightning Framework is a robust malware framework that consists of various modules and plugins with diverse capabilities, including the ability to download and install multiple types of rootkits. The framework targets Linux endpoints and utilizes several techniques to hide the presence of the malware. It also communicates with the threat actor using a combination of active and passive attack techniques. 

In this blog post, we identify Indicators of Compromise (IoC) for the Lightning Framework, and detect the activity of the malware using Wazuh.

Lightning Framework architecture

The Lightning Framework uses a modular architecture consisting of three modules listed below:

1. The downloader module (Lightning.Downloader): The malware downloader fetches multiple plugins and the core module from a remote server and executes the downloaded core module.

2. The core module (Lightning.Core): This is the main module of the framework. Fundamentally, it establishes a connection with the C2 server (command and control) and is capable of receiving commands, hiding malware artifacts, and executing the plugin modules.

3. The plugin modules: The plugins supported by the framework include the Plugin.Kernel, Plugin.RootkieHide, Plugin.SsHijacker, Plugin.Sshd, Plugin.Nethogs, Plugin.iftop, and Plugin.iptraf. The downloader module downloads these plugins to support the core module in the overall execution of the Lightning Framework.

Malware behavior analysis

  • The Lightning Framework infection chain starts with the Lightning.Downloader module. The downloader first verifies if it is presently located under the name kbioset within the /usr/lib64/seahorses/ working directory. To evade detection, the working directory of the downloader module uses typosquatting to masquerade as seahorses. This looks similar to a legitimate GNOME password and encryption key manager called seahorse. When the endpoint is infected, the downloader will copy itself to the /usr/lib64/seahorses/ directory and then execute itself.
# cd /usr/lib64/seahorses/
# ls
cpc  kbioset  kbioset.lock
  • Lightning.Downloader generates a GUID (globally unique identifier) by fingerprinting the network adapters and hostname of the endpoint. The GUID is sent to the C2 server which fetches and installs the other malware components and executes Lightning.Core on the endpoint.
  • Lightning.Core disguises itself as a legitimate kernel thread by using the prctl utility to rename its calling thread to kkdmflush. This is done within the earlier created /usr/lib64/seahorses/ directory as shown below:
# ls
cpc  kbioset  kbioset.lock  hpi  kkdmflush.lock
  • The core module establishes persistence by creating a /etc/rc.d/init.d/elastisearch file on the endpoint. The elastisearch file mimics the legitimate analytics engine, Elasticsearch.
# cd /etc/rc.d/init.d/
# ls
elastisearch  functions  README
  • Upon system boot, the malicious elastisearch script executes the downloader module and adds the persistent service using the chkconfig utility. The content of the script is shown below:
#!/bin/bash
# chkconfig:2345 90 20
/usr/lib64/seahorses/kbioset &

The command to execute the elastisearch script is shown below:

sh -c chkconfig -add elastisearch
  • The timestamp of the persistence elastisearch script is modified to match the timestamp of a fundamental Linux file such as find, whoami or su using a cloaking method called “timestomping”. 
  • The core module will then hide its PID (process ID) and associated network ports using a Linux kernel module (LKM) rootkit. The running PIDs of the malware are first written into two files named hpi and hpo. Both files are inspected, and a check is done for the presence of a /proc/y.y file path which verifies the existence of a rootkit. Once found, the PIDs get written to the /proc/y.y file which the rootkit uses to hide its PID from commands such as netstat, ps and ss, by removing any reference to the malicious framework.
  • A GUID is generated by Lightning.Core for communication with the C2 server using the same technique as the downloader module mentioned earlier. Based on responses from the C2, the core module is able to run shell commands, run plugins, fingerprint the endpoint, overwrite file contents, delete files or directories, send files to the C2, update or remove the malicious payload, and carry out many other actions based on the command executed. 
  • The Lightning.Core and Lightning.Downloader modules communicate over TCP sockets. The data structure uses the JSON format. 
  • The C2 profile is stored in a polymorphic encoded configuration file. This file cannot be detected by techniques that utilize hashes because it is unique for every creation instance. The analyzed malware sample makes use of a local IP address 10.2.22[.]67 with port 33229. Below we show the connection to the C2 server:
# netstat -antpl | egrep ':33229'
tcp   0   1   10.0.2.15:39730   10.2.22.67:33229   SYN_SENT   38951/kdmflush
  • The malware framework has its OpenSSH daemon named Linux.Plugin.Lightning.Sshd (sshod) to initiate a passive mode of communication. This plugin is used to start an SSH service on the infected endpoint. The Linux.Plugin.Lightning.Sshd plugin contains the attacker’s hardcoded SSH keys. Using the host key shown below, the attacker is able to create an SSH-based secondary backdoor by establishing an SSH session to the infected endpoint using their own SSH key.
# The attacker's hardcoded host key in the sshod plugin is shown below!

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJtfoCJIxOtTRnimA8Ut3KtrcCdHPAGMqeOJFnDZkI4FZHWl1hSkDUKUxxCLb/fLBMmDGZ0YYpUBQD9h3VltS5IR7Qe/wNV69w2iOvO10BEabskvPxBzjT1Tc6kDKYOdBh6PyI9HPeGEiSj13CyZcJ3sMg8vnEvFE2NH0CTv3ZBaI0YCNq14rUU2MRjsx9U7Sz3fJHhLQMvLVs33bVTsYCVzGAaTtjcxpffpEfvhTapVr2Ke9TMe81aYtGtVsSHLBjjMtNsKXH58NUth6YOT9oUKArEI/ojYKbFLV4zSbwqSBkhV2MLBzoV8agyheYW5uxUsL80Fo5baoKXZM/iziV root@desktop-udluksg

The hashes of some components of the Lightning Framework analyzed are shown below:

Filenamesha256
Lightning.Downloader48f9471c20316b295704e6f8feb2196dd619799edec5835734fc24051f45c5b7
Lightning.Corefd285c2fb4d42dde23590118dba016bf5b846625da3abdbe48773530a07bcd1e
Linux.Plugin.Lightning.Sshdad16989a3ebf0b416681f8db31af098e02eabd25452f8d781383547ead395237

The other components of the malware which are referenced based on strings and source code of the obtained framework modules are yet to be found in the wild and analyzed.

Detection with Wazuh

To understand the Lightning Framework malware and create detection mechanisms, we simulated and detected its activities using the following infrastructure:

1. A pre-built ready-to-use Wazuh OVA 4.3.9. Follow this guide to download the virtual machine.

2. CentOS 8.4.2105 endpoint with a Wazuh agent installed and enrolled to the Wazuh server. A Wazuh agent can be installed by following the deploying Wazuh agents guide.

The Wazuh capabilities we will utilize in detecting Lightning Framework malware are the Security Configuration Assessment (SCA) module and Osquery integration.

Security Configuration Assessment

The Wazuh SCA module is used to run checks that test system hardening, detect vulnerable software, and validate configuration policies. In this blog post, we utilize SCA to find the known IoCs of the Lightning Framework. 

Note

Root user privileges are required to run the commands described below.

Wazuh server

1. Create a new policy file /var/ossec/etc/shared/default/lightning_framework.yml:

policy:
  id: "lightning_framework"
  file: "lightning_framework.yml"
  name: "Lightning Framework Linux malware check"
  description: "Detecting Lightning Framework Linux malware"

requirements:
  title: "Checking Lightning Framework malware on Unix/Linux based systems."
  description: "Check that system is Unix/Linux based."
  condition: any
  rules:
	- 'f:/etc/passwd'
checks:
  - id: 20000
	title: "Checking for Lightning Framework artifacts in \"/usr/lib64/*\" directory"
	description: "Check for Lightning Framework Linux malware artifacts."
	condition: all
	rules:
  	- 'not c:find /usr/lib64/ -type d -name "seahorses" -> r:/usr/lib64/seahorses$'
  - id: 20001
	title: "Checking for Lightning Framework persistence"
	description: "Checking for Lightning Framework persistence."
	condition: all
	rules:
 	- 'not c:find /etc/rc.d/init.d/ -name "elastisearch" -> r:/etc/rc.d/init.d/elastisearch$'
  - id: 20002
	title: "Checking for Lightning Framework Linux Kernel Module rootkit"
	description: "Checking for Lightning Framework LKM rootkit."
	condition: all
	rules:
 	- 'not c:lsmod -> r:elastisearch'

2. Modify the owner and group of the newly created SCA policy file to belong to Wazuh:

# chown wazuh:wazuh /var/ossec/etc/shared/default/lightning_framework.yml

3. Edit /var/ossec/etc/shared/default/agent.conf to contain the SCA block. This SCA policy will be shared with all agents in the default group:

<agent_config os="linux">
  <sca>
    <enabled>yes</enabled>
    <scan_on_start>yes</scan_on_start>
    <interval>30m</interval>
    <skip_nfs>yes</skip_nfs>    
    <policies> 
      <policy>/var/ossec/etc/shared/lightning_framework.yml</policy>  
    </policies>
  </sca>
</agent_config>

4. Restart the Wazuh manager to apply the changes:

# systemctl restart wazuh-manager

Monitored endpoint

1. Edit the /var/ossec/etc/local_internal_options.conf file directly on the monitored Linux endpoint. This is to enable command execution in the SCA policies which are sent from the Wazuh server. By default, remote commands are disabled for security reasons and need to be explicitly enabled by users:

# echo "sca.remote_commands=1" >> /var/ossec/etc/local_internal_options.conf

2. Restart the Wazuh agent to apply the changes:

# systemctl restart wazuh-agent

Testing the configuration

To test that the SCA policy is working correctly, we run the malware samples within our sandboxed CentOS 8 endpoint. 

# ./Lightning.Downloader
# ./Lightning.Core
# ./Linux.Plugin.Lightning.Sshd

We can see the SCA scan results for an endpoint infected with Lightning Framework Linux malware:

Osquery integration

Using the Osquery integration, we are able to utilize SQL-based queries to detect the malware activities on the Linux endpoint. The data generated from Osquery is sent from the Wazuh agent to the Wazuh server, and the alerts can be viewed on the Wazuh dashboard.

We use an Osquery pack from Ryan Robinson to create the detection rules. The rules use information gathered via the reverse engineering process to detect Lightning Framework IoCs. Using this module we are able to find other related Lightning Framework samples with a unique file hash. To use Osquery with Wazuh to scan for the Lightning Framework IoCs, do the following:

Note

Root user privileges are required to run the commands described below.

Monitored endpoint

1. Install Osquery on the monitored endpoint:

# yum install yum-utils
# curl -L https://pkg.osquery.io/rpm/GPG | tee /etc/pki/rpm-gpg/RPM-GPG-KEY-osquery
# yum-config-manager --add-repo https://pkg.osquery.io/rpm/osquery-s3-rpm.repo
# yum-config-manager --enable osquery-s3-rpm-repo
# yum install osquery

2. Create a query pack /opt/osquery/share/osquery/packs/lightning.json. This file contains specific detection queries which are used to detect Lightning Framework file artifacts, malware persistence, and installed rootkits:

{
    "queries": {
        "artifacts": {
            "query": "SELECT path, filename, username, groupname, mtime, ctime, atime, md5, sha1, sha256 FROM file JOIN users using (uid) JOIN hash using (path) JOIN groups using (gid) WHERE file.directory in('/usr/lib64/seahorses/');",
            "interval": "60",
            "version": "1.0.0",
            "description": "https://www.intezer.com/blog/research/lightning-framework-new-linux-threat/",
            "platform": "linux",
            "value": "Possible Lightning Framework files"
        },
        "startup-item": {
            "query": "SELECT * FROM startup_items WHERE name = 'elastisearch';",
            "interval": "60",
            "version": "1.0.0",
            "description": "https://www.intezer.com/blog/research/lightning-framework-new-linux-threat/",
            "platform": "linux",
            "value": "Possible Lightning Framework startup item"
        },
        "kernel-module": {
            "query": "SELECT * FROM kernel_modules WHERE name = 'elastisearch';",
            "interval": "60",
            "version": "1.0.0",
            "description": "https://www.intezer.com/blog/research/lightning-framework-new-linux-threat/",
            "platform": "linux",
            "value": "Possible Lightning Framework rootkit"
        }
    }
}

Where:

  • artifacts is the query that detects the created malware artifacts.
  • startup-item is the query that detects the persistence startup script.
  • kernel-module is the query that detects the installed Linux kernel module rootkit.

3. Create a custom Osquery configuration file /etc/osquery/osquery.conf and add the newly created lightning.json query pack shown below:

Note

For users with Osquery previously installed and a /etc/osquery/osquery.conf file present, all you need to do is update the configuration file by adding the highlighted lightning-framework query pack shown below.

{
    "options": {
        "config_plugin": "filesystem",
        "logger_plugin": "filesystem",
        "utc": "true"
    },

    "schedule": {
        "system_info": {
        "query": "SELECT hostname, cpu_brand, physical_memory FROM system_info;",
        "interval": 3600
        },
        "high_load_average": {
        "query": "SELECT period, average, '70%' AS 'threshold' FROM load_average WHERE period = '15m' AND average > '0.7';",
        "interval": 900,
        "description": "Report if load charge is over 70 percent."
        },
        "low_free_memory": {
        "query": "SELECT memory_total, memory_free, CAST(memory_free AS real) / memory_total AS memory_free_perc, '10%' AS threshold FROM memory_info WHERE memory_free_perc < 0.1;",
        "interval": 1800,
        "description": "Free RAM is under 10%."
        }
    },

	"packs": {
      "lightning-framework": "/opt/osquery/share/osquery/packs/lightning.json",
    	"osquery-monitoring": "/opt/osquery/share/osquery/packs/osquery-monitoring.conf",
    	"incident-response": "/opt/osquery/share/osquery/packs/incident-response.conf",
    	"it-compliance": "/opt/osquery/share/osquery/packs/it-compliance.conf",
    	"vuln-management": "/opt/osquery/share/osquery/packs/vuln-management.conf",
    	"hardware-monitoring": "/opt/osquery/share/osquery/packs/hardware-monitoring.conf",
    	"ossec-rootkit": "/opt/osquery/share/osquery/packs/ossec-rootkit.conf"
	}
}

4. Validate the file to ensure there are no mistakes:

# osqueryctl config-check

5. Edit /var/ossec/etc/ossec.conf and enable the Osquery module:

<ossec_config>
  <wodle name="osquery">
  <disabled>no</disabled>
  <run_daemon>yes</run_daemon>
  <log_path>/var/log/osquery/osqueryd.results.log</log_path>
  <config_path>/etc/osquery/osquery.conf</config_path>
  <add_labels>yes</add_labels>
  </wodle>
</ossec_config>

6. Restart the Wazuh agent to apply the changes:

# systemctl restart wazuh-agent

Wazuh automatically reads the /var/log/osquery/osqueryd.results.log file and generates alerts related to these logs.

Testing the configuration

To view the Osquery events, it is necessary to enable the Osquery module on the Wazuh dashboard. This can be enabled on the Wazuh dashboard by navigating to Settings > Modules > Osquery and checking the box.

To test that the rules are working correctly, we trigger an alert by executing the obtained malware samples in our sandboxed CentOS 8 endpoint:

# ./Lightning.Downloader
# ./Lightning.Core
# ./Linux.Plugin.Lightning.Sshd

The screenshot below shows the alerts triggered by the Lightning Framework samples:

Conclusion

The Lightning Framework is a broad Linux malware framework that can compromise endpoints using various techniques. This versatile and complex framework is one of the recent malware strains targeting Linux endpoints. Wazuh has many modules that can be used in detecting the Lightning Framework. In this article, we have demonstrated how to detect the Lightning Framework using both the Wazuh SCA module and the Osquery integration with Wazuh. 

References

If you have any questions about this, join our Slack community channel!