Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include a virustotal-remove-threat.(sh|py) active response script to delete malicious files in Linux/Unix endpoints out-of-the-box using VirusTotal events #16646

Open
TheMuntu opened this issue Apr 6, 2023 · 0 comments

Comments

@TheMuntu
Copy link

TheMuntu commented Apr 6, 2023

Wazuh version Component Install type Install method Platform
4.4.X Wazuh agent (active response) Agent Packages/Sources Linux/Unix

Description

This issue aims to have a unified virustotal-remove-threat.sh or virustotal-remove-threat.py script that can be used to delete file on Linux/Unix endpoints after being flagged as malicious by VirusTotal . This out-of-the-box script will remove the need for users to write their own scripts to remove malicious files which may not be very effective for a wide range of events.

Sample scripts

This is a sample of a virustotal-remove-threat.sh script that can be improved and included out-of-the-box.

#!/bin/bash

LOCAL=`dirname $0`;
cd $LOCAL
cd ../

PWD=`pwd`

read INPUT_JSON
FILENAME=$(echo $INPUT_JSON | jq -r .parameters.alert.data.virustotal.source.file)
COMMAND=$(echo $INPUT_JSON | jq -r .command)
LOG_FILE="${PWD}/../logs/active-responses.log"

#------------------------ Analyze command -------------------------#
if [ ${COMMAND} = "add" ]
then
 # Send control message to execd
 printf '{"version":1,"origin":{"name":"remove-threat","module":"active-response"},"command":"check_keys", "parameters":{"keys":[]}}\n'

 read RESPONSE
 COMMAND2=$(echo $RESPONSE | jq -r .command)
 if [ ${COMMAND2} != "continue" ]
 then
  echo "`date '+%Y/%m/%d %H:%M:%S'` $0: $INPUT_JSON Remove threat active response aborted" >> ${LOG_FILE}
  exit 0;
 fi
fi

# Removing file
rm -f $FILENAME
if [ $? -eq 0 ]; then
 echo "`date '+%Y/%m/%d %H:%M:%S'` $0: $INPUT_JSON Successfully removed threat" >> ${LOG_FILE}
else
 echo "`date '+%Y/%m/%d %H:%M:%S'` $0: $INPUT_JSON Error removing threat" >> ${LOG_FILE}
fi

exit 0;

This is a sample of a virustotal-remove-threat.py script that can be improved and included out-of-the-box.

#!/usr/bin/python3
# Copyright (C) 2015-2022, Wazuh Inc.
# All rights reserved.

import os
import sys
import json
import datetime

if os.name == 'nt':
    LOG_FILE = "C:\\Program Files (x86)\\ossec-agent\\active-response\\active-responses.log"
else:
    LOG_FILE = "/var/ossec/logs/active-responses.log"

ADD_COMMAND = 0
DELETE_COMMAND = 1
CONTINUE_COMMAND = 2
ABORT_COMMAND = 3

OS_SUCCESS = 0
OS_INVALID = -1

class message:
    def __init__(self):
        self.alert = ""
        self.command = 0

def write_debug_file(ar_name, msg):
    with open(LOG_FILE, mode="a") as log_file:
        log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name + ": " + msg +"\n")

def setup_and_check_message(argv):

    # get alert from stdin
    input_str = ""
    for line in sys.stdin:
        input_str = line
        break


    try:
        data = json.loads(input_str)
    except ValueError:
        write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
        message.command = OS_INVALID
        return message

    message.alert = data

    command = data.get("command")

    if command == "add":
        message.command = ADD_COMMAND
    elif command == "delete":
        message.command = DELETE_COMMAND
    else:
        message.command = OS_INVALID
        write_debug_file(argv[0], 'Not valid command: ' + command)

    return message


def send_keys_and_check_message(argv, keys):

    # build and send message with keys
    keys_msg = json.dumps({"version": 1,"origin":{"name": argv[0],"module":"active-response"},"command":"check_keys","parameters":{"keys":keys}})

    write_debug_file(argv[0], keys_msg)

    print(keys_msg)
    sys.stdout.flush()

    # read the response of previous message
    input_str = ""
    while True:
        line = sys.stdin.readline()
        if line:
            input_str = line
            break

    # write_debug_file(argv[0], input_str)

    try:
        data = json.loads(input_str)
    except ValueError:
        write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
        return message

    action = data.get("command")

    if "continue" == action:
        ret = CONTINUE_COMMAND
    elif "abort" == action:
        ret = ABORT_COMMAND
    else:
        ret = OS_INVALID
        write_debug_file(argv[0], "Invalid value of 'command'")

    return ret

def main(argv):

    write_debug_file(argv[0], "Started")

    # validate json and get command
    msg = setup_and_check_message(argv)

    if msg.command < 0:
        sys.exit(OS_INVALID)

    if msg.command == ADD_COMMAND:
        alert = msg.alert["parameters"]["alert"]
        keys = [alert["rule"]["id"]]
        action = send_keys_and_check_message(argv, keys)

        # if necessary, abort execution
        if action != CONTINUE_COMMAND:

            if action == ABORT_COMMAND:
                write_debug_file(argv[0], "Aborted")
                sys.exit(OS_SUCCESS)
            else:
                write_debug_file(argv[0], "Invalid command")
                sys.exit(OS_INVALID)

        try:
            os.remove(msg.alert["parameters"]["alert"]["data"]["virustotal"]["source"]["file"])
            write_debug_file(argv[0], json.dumps(msg.alert) + " Successfully removed threat")
        except OSError as error:
            write_debug_file(argv[0], json.dumps(msg.alert) + "Error removing threat")


    else:
        write_debug_file(argv[0], "Invalid command")

    write_debug_file(argv[0], "Ended")

    sys.exit(OS_SUCCESS)

if __name__ == "__main__":
    main(sys.argv)

Expected configuration

To use this script, add the following configuration to the Wazuh server /var/ossec/etc/ossec.conf file:

<command>
   <name>virustotal-remove-threat</name>
   <executable>virustotal-remove-threat.sh</executable>
   <timeout_allowed>no</timeout_allowed>
</command>

<active-response>
   <disabled>no</disabled>
   <command>virustotal-remove-threat</command>
   <location>local</location>
   <rules_id><USER_DEFINED_RULES_ID></rules_id>
</active-response>

Reference: Using the VirusTotal integration and FIM

Expected execution flow

The steps for the execution of this active response script virustotal-remove-threat.sh will be:

  • File integrity monitoring is configured for directories of interest.
  • The active response parameters are configured on the Wazuh server to execute the remove threat script when specific rules (rules that indicate that a file has been detected as malware) are triggered.
  • A new file is downloaded to the monitored directory on the Linux/Unix endpoint.
  • This file is detected as malware on VirusTotal.
  • The file is removed by the active response script.

Detection alert samples (Retrieved from Ubuntu 22.04)

  • File detected as malware using VirusTotal.
{
  "agent": {
    "ip": "10.0.2.15",
    "name": "Ubuntu",
    "id": "003"
  },
  "manager": {
    "name": "wazuh-manager"
  },
  "data": {
    "integration": "virustotal",
    "virustotal": {
      "sha1": "3395856ce81f2b7382dee72602f798b642f14140",
      "malicious": "1",
      "total": "68",
      "found": "1",
      "positives": "65",
      "source": {
        "sha1": "3395856ce81f2b7382dee72602f798b642f14140",
        "file": "/root/eicar.com",
        "alert_id": "1667213918.2984352",
        "md5": "44d88612fea8a8f36de82e1278abb02f"
      },
      "permalink": "https://www.virustotal.com/gui/file/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f/detection/f-275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f-1667213857",
      "scan_date": "2022-10-31 10:57:37"
    }
  },
  "rule": {
    "firedtimes": 1,
    "mail": true,
    "level": 12,
    "pci_dss": [
      "10.6.1",
      "11.4"
    ],
    "description": "VirusTotal: Alert - /root/eicar.com - 65 engines detected this file",
    "groups": [
      "virustotal"
    ],
    "mitre": {
      "technique": [
        "Exploitation for Client Execution"
      ],
      "id": [
        "T1203"
      ],
      "tactic": [
        "Execution"
      ]
    },
    "id": "87105",
    "gdpr": [
      "IV_35.7.d"
    ]
  },
  "decoder": {
    "name": "json"
  },
  "input": {
    "type": "log"
  },
  "@timestamp": "2022-10-31T10:58:51.075Z",
  "location": "virustotal",
  "id": "1667213931.2985272",virustotal-remove-threat.sh
  "timestamp": "2022-10-31T10:58:51.075+0000",
  "_id": "DjSxLYQBlJASCy1-3GQd"
}

Expected outcome: The file is deleted.
Fields of interest: data.virustotal.source.file.
Alert generation guide: [Using the VirusTotal integration and FIM](https://documentation.wazuh.com/current/proof-of-concept-guide/detect-remove-malware-virustotal.html).

General notes

  • The script should be modified to work also on macOS.
  • The script should be able to generate alerts for when the file does not exist, and other possible error cases.
  • In addition to creating the script, the documentation should be updated to include instructions and examples for using the active response script.
@Spades0 Spades0 changed the title Include a virustotal-remove-threat.(sh|py) active response script to delete malicious files in Linux/Unix endpoints out-of-the-box using VirusTotal events Include a virustotal-remove-threat.(sh|py) active response script to delete malicious files in Linux/Unix endpoints out-of-the-box using VirusTotal events Apr 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants