Conducting container vulnerability scans is an approach to protecting containers and the infrastructure that supports them. Containers provide isolated environments for applications, maintaining consistency across other platforms. Detecting and resolving security threats within containers through container vulnerability scanning is an essential proactive security practice. This is important given the dynamic nature of software and the associated security risks, helping prevent exploitation by malicious actors.

Snyk is a software security platform that helps developers and organizations find and fix vulnerabilities in open source dependencies and their applications. It has a Command-Line Interface (CLI) which is used for addressing container vulnerabilities. It enables thorough container vulnerability scanning, ensuring the robust examination of container images, libraries, and dependencies to uncover potential security flaws. This proactive security measure strengthens container security in various environments.

Wazuh is a free, open source, enterprise-grade security monitoring platform that provides comprehensive protection for cloud, on-premises, containerized, and virtualized environments. It provides visibility across the environments to enable users to detect threats, maintain the integrity of files, respond to security incidents, and meet compliance requirements. 

By combining the capabilities of the Snyk CLI and Wazuh, organizations can implement a robust strategy for container vulnerability scanning, significantly minimizing the risk of security breaches and bolstering the overall security posture of their containerized environments.

Infrastructure

1. A pre-built, ready-to-use Wazuh OVA 4.6.0 Follow this guide to download the virtual machine (VM). This VM hosts the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard).

2. An Ubuntu 22.04 LTS endpoint with Wazuh agent 4.6.0 installed and enrolled to the Wazuh server. To install the Wazuh agent, refer to the following installation guide

3. An active Snyk account. To create one, follow the Snyk user guide.

Configuration

First, we set up Docker Engine on the Ubuntu endpoint and deploy some containers to scan. Next, we run a custom bash script using the Wazuh Command module to  trigger Snyk CLI. This helps us to conduct a container vulnerability scan on the container images available on the Ubuntu endpoint.

Once the scanning is complete, we configure custom rules on the Wazuh server, enabling it to capture and monitor the outcomes of the Snyk scan conducted on the Ubuntu endpoint.

Ubuntu endpoint

Follow the steps below to perform the configurations on the Ubuntu endpoint:

Docker Engine installation & container initialization

We set up a Docker environment with running containers to check their vulnerability status.

Follow the steps below to install Docker Engine and deploy containers on the Ubuntu endpoint.

1. Update the package information from all configured sources:

$ sudo apt-get update

2. Install ca-certificates, curl, and gnupg:

$ sudo apt-get install ca-certificates curl gnupg

3. Create a directory named keyrings in the /etc/apt directory and set its permissions:

$ sudo install -m 0755 -d /etc/apt/keyrings

4. Download the Docker GPG key, convert it into a binary format, and store it in the /etc/apt/keyrings/docker.gpg file. This GPG key is used to verify the authenticity of Docker packages when they are installed or updated on the Ubuntu endpoint.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

5. Change the permissions of the /etc/apt/keyrings/docker.gpg file to allow read access to all users on the system:

$ sudo chmod a+r /etc/apt/keyrings/docker.gpg

6. Generate the repository source configuration for Docker, and append it to the /etc/apt/sources.list.d/docker.list file:

$ echo \
   "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
   "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

7. Update the package information from all configured sources with the command below:

$ sudo apt-get update

8. Install the required docker binaries:

$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

9. Create a new project directory named /container_env in the current user’s /Documents directory for the container environment and switch into it using the following command:

$ mkdir ~/Documents/container_env && cd $_

10. Create a  file docker-compose.yml  in the ~/Documents/container_env directory with the command below:

$ nano ./docker-compose.yml

11. Add the following configuration to the file:

version: '3'
services:
  nginx-container:
    image: nginx
    ports:
      - "80:80"

  redis-container:
    image: redis
    ports:
      - "6379:6379"

  postgres-container:
    image: postgres
    environment:
      POSTGRES_USER: wazuh_postgress
      POSTGRES_PASSWORD: wazuh_password
      POSTGRES_DB: wazuh_database
    ports:
      - "5432:5432"

The content of the docker-compose.yml file includes the configuration details for deploying  Redis, NGINX, and Postgres containers. In this context, they serve as the containers that will be scanned for vulnerabilities.

12. Run the command below to deploy and start the containers:

$ sudo docker compose up -d

13. Verify that the containers are up and running:

$ sudo docker ps 

Note: When you run the docker ps command, it displays a list of running containers. Make sure that the status for the containers you expect to be running is displayed as “Up”. If the status is anything other than “Up”, it means that the container is not running as expected, and you may need to investigate and troubleshoot the issue.

Snyk CLI installation

We download the Linux version of the Snyk CLI binary, adjust its permissions, and relocate it to a directory accessible to all users.

Follow the steps below to install the Snyk CLI:

1. Download the Linux version of the Snyk CLI binary and save it using the filename snyk:

$ curl --compressed https://static.snyk.io/cli/latest/snyk-linux -o snyk

2. Add the executable permission for all classes to the snyk binary:

$ chmod +x ./snyk

3. Move the snyk binary to the /usr/local/bin/ directory for all users to access it:

$ sudo mv ./snyk /usr/local/bin/

Authenticating the Snyk CLI with your Snyk account

This section provides step by step instructions for authenticating the Snyk CLI with your Snyk account on the Ubuntu endpoint. 

1. Login to your Snyk account

2. Select the Account settings option located in the dropdown menu at the bottom of the left navigation menu on the Web UI.

3. Click the click to show box and copy your API token in the KEY box.

Container vulnerability scanning

4. Run the following command to log in to your Snyk account and authenticate the CLI:

$ snyk auth <TOKEN>

NOTE: Replace the <TOKEN> placeholder with the API token copied in step 3 above.

Output
Your account has been authenticated. Snyk is now ready to be used.

jq installation

jq is a versatile and lightweight command-line JSON processor. The jq binary is important in facilitating the processing of JSON results generated by the Snyk Command-Line Interface (CLI) binary in the script. 

We obtain the Linux version of the jq binary from the Ubuntu repository by installing it with the command below:

$ sudo yes | sudo apt install jq

Vulnerability scanning script

We set up a Bash script for scanning containers residing on the Ubuntu endpoint. Additionally, we configure the Wazuh command module to execute the Snyk script on the agent host periodically. Follow the steps below to configure command monitoring on the container host.

1. Create and switch into a custom script directory /var/ossec/custom-script/ using the following command:

$ sudo mkdir /var/ossec/custom-script/ && cd $_

2. Create a new file snyk-vulns.sh:

$ sudo touch ./snyk-vulns.sh

3. Copy and paste the code below to the /var/ossec/custom-script/snyk-vulns.sh file. This script lists all running containers and iterates through them to perform scans using the Snyk CLI binary. Subsequently, it writes the scan results to the /var/ossec/logs/container_vulnerability_scan.log file:

#!/bin/bash
# Copyright (C) 2015-2023, Wazuh Inc.


# Function to log messages with a timestamp
log_message() {
    local message="$1"
    local log_file="$2"
    local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo "[$timestamp] $message" >> "$log_file"
}

# Define the log file path for all container vulnerability scan
log_file_path="/var/ossec/logs/container_vulnerability_scan.log"

# Check if the Docker command is available and print the filepath
if ! command -v docker &>/dev/null; then
    log_message "Docker command not found. Make sure Docker is installed and accessible." "$log_file_path"
    exit 1
fi

# Get the current date and time
current_datetime=$(date +"%Y-%m-%d %H:%M:%S")

# Run the Docker command to retrieve a list of images
docker_images=($(docker image ls --format "{{.Repository}}:{{.Tag}}"))

# Check if the Docker image list retrieval was successful
if [ $? -eq 0 ]; then
    log_message "Docker image list retrieved successfully at $current_datetime" "$log_file_path"
    log_message "Running vulnerability scans for Docker images:" "$log_file_path"

    # Define the Snyk_command template
    snyk_command_template="snyk container test \$container --json | jq '.vulnerabilities' | jq '.[] | {from, packageName, severity, id, name, version, description, nearestFixedInVersion, dockerfileInstruction, dockerBaseImage, nvdSeverity, publicationTime, malicious, title, cvssScore, identifiers}' | jq -c '.'"

    # Iterate through the list of Docker images and run vulnerability scans
    for image in "${docker_images[@]}"; do
        # Replace $container with the current image in Snyk_command
        snyk_command="${snyk_command_template//\$container/$image}"

        log_message "Running Snyk scan for: $image" "$log_file_path"

        # Execute the Snyk vulnerability scanning command and append the results to the log file
        eval "$snyk_command" >> "$log_file_path"
    done

    log_message "Vulnerability scans completed at $current_datetime" "$log_file_path"
else
    log_message "Failed to retrieve the Docker image list." "$log_file_path"
fi

4. Add the executable permission for all classes to the /var/ossec/custom-script/snyk-vulns.sh script:

$ sudo chmod +x snyk-vulns.sh

5. Change the ownership for the /var/ossec/custom-script/snyk-vulns.sh script and the directory where it is located:

$ sudo chown root:wazuh /var/ossec/custom-script/ -R

6. Generate the md5 hash for the /var/ossec/custom-script/snyk-vulns.sh script. This md5 hash is important to  be added to the <verify_md5> block, to ensure the integrity of the /var/ossec/custom-script/snyk-vulns.sh script.

$ md5sum /var/ossec/custom-script/snyk-vulns.sh

7. Edit the Wazuh agent /var/ossec/etc/ossec.conf file and add the following command module configuration within the <ossec_config> block:

  <!-- Run the container scanner script -->
  <wodle name="command">
    <disabled>no</disabled>
    <command>/var/ossec/custom-script/snyk-vulns.sh</command>
    <interval>7d</interval>
    <ignore_output>no</ignore_output>
    <run_on_start>yes</run_on_start>
    <timeout>0</timeout>
    <verify_md5>62230aa92230a19539db286e59626db1</verify_md5>
  </wodle>

Where:

  • disabled: Specifies that the Snyk command module is set to active.
  • Command: Specifies the location of the snyk-vulns.sh script to be executed.
  • interval: Specifies the time interval for the execution of the configured script. In this scenario, the set value executes the snyk-vulns.sh every 7 days. You have the flexibility to adjust this value to your preferred time interval.
  • Run_on_start: Specifies that the command module for the snyk-vulns.sh script runs immediately when the Wazuh service starts.
  • timeout: The timeout option is configured with a value of 0, the snyk-vulns.sh process will completely execute without any imposed time restrictions to halt it.
  • verify: Specifies the MD5 sum of the snyk-vulns script to ensure the integrity of the script to be executed. Ensure you replace the value of the <verify_md5> tag with your computed md5sum hash if you modify the script.

Wazuh agent

We configure the Wazuh agent to monitor and forward the content of the container_vulnerability_scan.log file to the Wazuh manager. This log file is subject to predefined rule sets, which will be established in the configuration detailed in Snyk rules configuration section. Follow the steps below for guidance:

1. Open the Wazuh agent configuration file:

# nano /var/ossec/etc/ossec.conf

2. Append the following configuration to the ossec_conf section in the /var/ossec/etc/ossec.conf file of the  monitored endpoint:

<localfile>
  <log_format>syslog</log_format>
  <location>/var/ossec/logs/container_vulnerability_scan.log</location>
</localfile>

3. Restart the Wazuh agent to apply this change:

# systemctl restart wazuh-agent

Wazuh server

Follow the steps below to perform the configurations of the Wazuh server:

Snyk rules configuration

We create rules in the Wazuh server to capture the result of the Snyk scan on the monitored Ubuntu endpoint. 

1. Create a rule file in the /var/ossec/etc/rules/ directory on the Wazuh server with the command below:

# nano /var/ossec/etc/rules/snyk-vulns_rules.xml

2. Add the custom rules below to the /var/ossec/etc/rules/snyk-vulns_rules.xml file:

<group name="containers, snyk-vulnerabilities,">


<!-- This rule detects the json output of snyk vulnerability scan.-->
  <rule id="111160" level="0">
    <decoded_as>json</decoded_as>
    <field name="packageName">\.+</field>
    <field name="cvssScore">\.+</field>
    <field name="dockerBaseImage">\.+</field>
    <description>Snyk: Alert</description>
  </rule>
    
<!-- This rule detects the critical severity vulnerability for the Snyk scan.-->
  <rule id="111161" level="14">
    <if_sid>111160</if_sid>
    <field name="severity">critical</field>
    <description>Snyk Critical Alert: Vulnerable Package $(packageName) $(version) Detected in $(from) Container</description>
  </rule>

<!-- This rule detects the high severity vulnerability for the Snyk scan.-->
  <rule id="111162" level="12">
    <if_sid>111160</if_sid>
    <field name="severity">high</field> 
    <description>Snyk High Alert: Vulnerable Package $(packageName) $(version) Detected in $(from) Container</description>
  </rule>

<!-- This rule detects the medium severity vulnerability for the Snyk scan.-->
  <rule id="111163" level="10">
    <if_sid>111160</if_sid>
    <field name="severity">medium</field>
    <description>Snyk Medium Alert: Vulnerable Package $(packageName) $(version) Detected in $(from) Container</description>
  </rule>

<!-- This rule detects the low severity vulnerability for the Snyk scan.-->
  <rule id="111164" level="7">
    <if_sid>111160</if_sid>
    <field name="severity">low</field>
    <description>Snyk Low Alert: Vulnerable Package $(packageName) $(version) Detected in $(from) Container</description>
  </rule>

</group>

Where:

  • Rule ID 111160 detects the JSON output of the Snyk vulnerability scan.
  • Rule ID 111161 detects the critical severity vulnerabilities from the Snyk scan.
  • Rule ID 111162 detects the high severity vulnerabilities from the Snyk scan.
  • Rule ID 111163 detects the medium severity vulnerabilities from the Snyk scan.
  • Rule ID 111164 detects the low severity vulnerabilities from the Snyk scan.

3. Save and close the snyk-vulns_rules.xml rule file.

4. Restart the Wazuh manager to apply the configuration changes:

# systemctl restart wazuh-manager

Container vulnerability scanning results

Below are the images of the alerts generated on the Wazuh dashboard when Snyk discovers a vulnerability on the containers present on an Ubuntu endpoint for vulnerabilities.

Critical severity alerts

1. Navigate to the Security events tab and input the Dashboards Query Language (DQL) rule.id:111161 in the HTML form. Next, click the update/refresh button to view the critical severity alerts:

Critical Severity Alerts

High severity alerts

1. Navigate to the Security events tab and input the Dashboards Query Language (DQL) rule.id:111162 in the HTML form. Next, click the update/refresh button to view the High severity alerts:

High severity alerts

Medium severity scans alerts

1. Navigate to the Security events tab and input the Dashboards Query Language (DQL) rule.id:111163 in the HTML form. Next, click the update/refresh button to view the Medium severity alerts:

Medium severity alerts

Low severity alerts

1. Navigate to the Security events tab and input the Dashboards Query Language (DQL) rule.id:111161 in the HTML form. Next, click the refresh button to view the Low severity alerts:

Container vulnerability scanning Low severity alerts

Conclusion

In this blog post, we showcase how integrating Snyk with Wazuh enables organizations to conduct vulnerability scans within their container environments. This integration allows organizations to enhance their container security practices by promptly identifying and remediating vulnerabilities.

Wazuh is an open source security monitoring platform that provides a unified security management approach across various operating systems. It provides capabilities such as security analytics, intrusion detection, file integrity monitoring, vulnerability detection, incident response, and more. To learn more about Wazuh, please check out our other blog posts and official guides.

Reference