Grype is a lightweight, open source tool for scanning container images and filesystems for vulnerabilities. It examines container image layers and dependencies to identify known vulnerabilities in the software packages installed within the image. By inspecting each layer and its contents, Grype helps you proactively uncover potential security risks before deploying the container image into a production environment.
Wazuh is a free and open source enterprise security platform that provides several capabilities and features to help organizations secure their cloud, on-premises, and container environments. This includes centralized logging, real-time monitoring, incident response automation, and others.
By integrating Grype with Wazuh, you can gain a comprehensive view of your container security posture and take proactive measures to address identified threats. This process can be integrated into your CI/CD pipeline or DevOps workflow. In this blog post, we explore how to leverage the capabilities of Grype and Wazuh to implement effective container image vulnerability scanning.
Infrastructure
To demonstrate the integration of Grype and Wazuh for container image vulnerability scanning, we use the following infrastructure:
- A pre-built, ready-to-use Wazuh OVA 4.8.0 which includes the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow this guide to download and set up the Wazuh virtual machine.
- An Ubuntu 22.04 endpoint with Wazuh agent 4.8.0 installed and enrolled to the Wazuh server. We install Grype version 0.78.0 on this endpoint.
Configuration
In this section, we set up Docker Engine and deploy container images on the monitored Ubuntu 22.04 endpoint. Next, we install Grype, create a custom bash script, and then use the Wazuh Command module to reference the script. The script scans the endpoint to detect existing container images and runs a vulnerability scan with Grype. Finally, we create and configure custom Wazuh decoders and rules on the Wazuh server to process and monitor the logs generated from the Grype scan.
Ubuntu
Perform the following steps on the Ubuntu endpoint to set up Docker Engine, deploy container images, and install Grype.
Install Docker Engine and pull container images
Follow the steps below to install Docker Engine and deploy container images on the Ubuntu endpoint.
Note: You need root user privileges to execute all the commands described below.
1. Update the list of available packages and their versions, and install the cURL package:
# apt update && apt install curl -y
2. Run the following commands to download and run the Docker installation script:
# curl -sSL https://get.docker.com/ | sh
3. The Docker service starts automatically on Debian-based distributions. On RPM-based distributions, start the Docker service with the following command:
# systemctl start docker
4. Create and switch into a project directory /container_env
for the container environment using the following command:
# mkdir /container_env && cd $_
5. Create a configuration file docker-compose.yml
in the container_env
directory:
# touch docker-compose.yml
6. Copy and paste the configuration below into the docker-compose.yml
file. This configuration file defines a development environment for a Node.js application that interacts with a MongoDB database and a Redis cache:
services: nodejs: image: node:latest container_name: nodejs_container restart: always ports: - 3000:3000 volumes: - ./app:/app working_dir: /app environment: - NODE_ENV=production mongo: image: mongo:latest container_name: mongo_container restart: always redis: image: redis:latest container_name: redis_container restart: always
Note: You can configure the services further, however in this example, the focus is on pulling the base images (node:latest
, mongo:latest
, and redis:latest
). These are the container images that will be scanned for vulnerabilities.
7. Run the command below to pull the container images using Docker Compose:
# docker compose pull
8. Verify that the container images are present:
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 1a83fd5edeed 6 days ago 117MB node latest 3d4b037e6712 13 days ago 1.11GB mongo latest ff65a94ec485 4 weeks ago 795MB
Install Grype
1. Run the following command to download and execute the Grype installation script:
# curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sudo sh -s -- -b /usr/local/bin
2. Verify that Grype has been installed:
# grype --version
grype 0.78.0
3. Run the following command to update the Grype vulnerability database:
# grype db update
Create a custom bash script and configure the Wazuh Command module
Follow the steps below to create a bash script and configure the Wazuh Command module on the Ubuntu endpoint. The script scans the endpoint to detect existing container images and runs a vulnerability scan with Grype. The Wazuh Command module is configured to monitor the output of the script and treat it as log content.
1. Create a custom script directory /var/ossec/custom-script/
and create a new file grype_scan.sh
using the following command:
# mkdir /var/ossec/custom-script/ && touch /var/ossec/custom-script/grype_scan.sh
2. Copy and paste the code below into the /var/ossec/custom-script/grype_scan.sh
file:
#!/bin/bash # Copyright (C) 2015-2023, Wazuh Inc. # Directory to save the custom output template TEMPLATE_DIR="/tmp" TEMPLATE_FILE="$TEMPLATE_DIR/custom.tmpl" # Create the custom output template (unchanged) cat <<EOL > "$TEMPLATE_FILE" "Package","Version Installed","Vulnerability ID","Severity" {{- range .Matches}} "{{.Artifact.Name}}","{{.Artifact.Version}}","{{.Vulnerability.ID}}","{{.Vulnerability.Severity}}" {{- end }} EOL # Retrieve list of container images images=$(docker images --format "{{.Repository}}:{{.Tag}}") # Loop through each container image and run Grype scan for image in $images; do # Run Grype scan on the current image using the custom output template grype_output=$(grype $image -o template -t $TEMPLATE_FILE) # Process Grype output for the current image while IFS= read -r line; do # Prepend image name with quotes and comma formatted_line=Grype:"\"$image\","$line # Print the formatted line with quoted image name echo "$formatted_line" done <<< "$grype_output" done # Clean up the custom output template rm -f "$TEMPLATE_FILE"
This script sets up a custom output template for Grype. Then, it retrieves a list of container images and executes a Grype scan on each container image. Subsequently, it formats the output by adding “Grype
:” at the start of each line. Finally, it cleans up the temporary output template file.
3. Add the executable permission for all classes to the /var/ossec/custom-script/grype_scan.sh
file:
# chmod +x /var/ossec/custom-script/grype_scan.sh
4. Change the ownership of the /var/ossec/custom-script/grype_scan.sh
file and the directory where it is located:
# chown root:wazuh /var/ossec/custom-script/ -R
5. Edit the Wazuh agent /var/ossec/etc/ossec.conf
file and add the following Command module configuration within the <ossec_config>
block:
<!-- Grype container vulnerability scanner script --> <wodle name="command"> <disabled>no</disabled> <command>/var/ossec/custom-script/grype_scan.sh</command> <interval>5d</interval> <ignore_output>no</ignore_output> <run_on_start>yes</run_on_start> <timeout>0</timeout> </wodle>
Where:
disabled
specifies that the Grype command is set to active.command
specifies the location of thegrype_scan.sh
script to be executed.interval
specifies the time interval for the execution of the configured script. In this blog post, the set value executes thegrype_scan.sh
every 5 days. Set this value to your preferred time interval.ignore_output
determines whether the output of the command execution should be ignored. Setting it tono
means that the output will be processed and logged by Wazuh.run_on_start
specifies that the command module configuration for thegrype_scan.sh
script runs immediately when the Wazuh service starts.timeout
sets the timeout option to 0. This means thegrype_scan.sh
process will execute without any imposed time restrictions to halt it.
6. Restart the Wazuh agent to apply the above changes:
# systemctl restart wazuh-agent
Wazuh server
Perform the steps below on the Wazuh server. We create and configure custom Wazuh decoders and rules on the Wazuh server to process and monitor the logs generated from the Grype scan.
Note: You need root user privileges to execute all the commands described below.
1. Create a file grype_decoders.xml
in the /var/ossec/etc/decoders/
directory.
# touch /var/ossec/etc/decoders/grype_decoders.xml
2. Add the following Wazuh decoder to the /var/ossec/etc/decoders/grype_decoders.xml
file to parse the Grype logs received from the Wazuh agent:
<decoder name="grype-decoder"> <prematch>^Grype:</prematch> </decoder> <decoder name="grype-decoder-fields"> <parent>grype-decoder</parent> <regex offset="after_parent">"(\.+)","(\.+)","(\.+)","(\.+)","(\.+)"</regex> <order>image, package, version, vulnerability_id, severity</order> </decoder>
3. Create a file grype_rules.xml
in the /var/ossec/etc/rules/
directory:
# touch /var/ossec/etc/rules/grype_rules.xml
4. Add the following Wazuh rules to the /var/ossec/etc/rules/grype_rules.xml
file to detect the Grype scan results:
<group name="grype"> <!-- Parent Rule for Grype alerts --> <rule id="100101" level="0"> <decoded_as>grype-decoder</decoded_as> <description>Grype alert detected.</description> </rule> <!-- This rule detects a critical severity vulnerability in a container image --> <rule id="100102" level="14"> <if_sid>100101</if_sid> <field name="severity">Critical</field> <description>Grype alert [Critical]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a high severity vulnerability in a container image --> <rule id="100103" level="12"> <if_sid>100101</if_sid> <field name="severity">High</field> <description>Grype alert [High]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a medium severity vulnerability in a container image --> <rule id="100104" level="7"> <if_sid>100101</if_sid> <field name="severity">Medium</field> <description>Grype alert [Medium]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a low severity vulnerability in a container image --> <rule id="100105" level="4"> <if_sid>100101</if_sid> <field name="severity">Low</field> <description>Grype alert [Low]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a negligible severity vulnerability in a container image --> <rule id="100106" level="1"> <if_sid>100101</if_sid> <field name="severity">Negligible</field> <description>Grype alert [Negligible]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects an unknown severity vulnerability in a container image --> <rule id="100107" level="7"> <if_sid>100101</if_sid> <field name="severity">Unknown</field> <description>Grype alert [Unknown]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> </group>
Where:
- Rule ID
100101
detects the output of the Grype vulnerability scan. This rule will not generate alerts on the Wazuh dashboard, because, by default, alerts with levels below 3 do not appear on the Wazuh dashboard. - Rule ID
100102
detects the critical severity vulnerabilities from the Grype scan. - Rule ID
100103
detects the high severity vulnerabilities from the Grype scan. - Rule ID
100104
detects the medium severity vulnerabilities from the Grype scan. - Rule ID
100105
detects the low severity vulnerabilities from the Grype scan. - Rule ID
100106
detects the negligible severity vulnerabilities from the Grype scan. This rule will not generate alerts on the Wazuh dashboard, because, by default, alerts with levels below 3 do not appear on the Wazuh dashboard. You can modify the rule level at your discretion. - Rule ID
100107
detects the unknown severity vulnerabilities from the Grype scan.
5. Restart the Wazuh manager to apply the above changes:
# systemctl restart wazuh-manager
Visualizing vulnerability alerts on the Wazuh dashboard
Perform the following steps to view the alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype
in the filter bar and hit the Enter button on your keyboard.
3. Under Available fields, add the following fields as columns by hovering on each field and clicking the + icon beside it: agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
.
Note: If you do not see the fields under Available fields, refresh the fields list from the Index Patterns page. To do this, navigate to Dashboard Management > Index Patterns. Select wazuh-alerts-* from the list then click the refresh icon ⟳.
We filter further to identify and visualize alerts for each vulnerability severity.
Critical vulnerability alerts
Perform the following steps to view the critical severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype and rule.id:100102
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
and clicking the + icon beside it.
4. Save the query as Grype [Critical vulnerabilities].
High vulnerability alerts
Perform the following steps to view the high severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype and rule.id:100103
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
and clicking the + icon beside it.
4. Save the query as Grype [High vulnerabilities]. Ensure you select the Save as new search option.
Medium vulnerability alerts
Perform the following steps to view the medium severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype and rule.id:100104
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
and clicking the + icon beside it.
4. Save the query as Grype [Medium vulnerabilities]. Ensure you select the Save as new search option.
Low vulnerability alerts
Perform the following steps to view the low severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype and rule.id:100105
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
and clicking the + icon beside it.
4. Save the query as Grype [Low vulnerabilities]. Ensure you select the Save as new search option.
Unknown vulnerability alerts
Perform the following steps to view the unknown severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:grype and rule.id:100107
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.severity
, data.vulnerability_id
, data.package
, and data.version
and clicking the + icon beside it.
4. Save the query as Grype [Unknown vulnerabilities]. Ensure you select the Save as new search option.
Note: Sometimes Grype generates vulnerabilities with “unknown” severity. This can arise from incomplete data, zero-day vulnerabilities, or differing vendor classifications and does not mean no risk exists. Investigate these findings using the provided details (ID, package, version) to assess potential impact.
Creating a custom dashboard
Create a custom dashboard with the saved templates for a single visualization display.
1. Navigate to Explore > Dashboards > Create New Dashboard.
2. Select Add an existing link and click the saved visualizations (Grype [Critical vulnerabilities], Grype [High vulnerabilities], Grype [Unknown vulnerabilities]). This will add the visualizations to the new dashboard.
3. Save the dashboard as Grype container image vulnerabilities.
Conclusion
This blog post highlights the steps for integrating Grype with Wazuh to scan container images in your containerized environment. This integration can enhance your overall security posture by providing automated vulnerability scanning of container images before they are deployed in your environment.
Wazuh is an open source security monitoring platform that provides a unified security management approach across various operating systems. Wazuh also has container security capabilities which when combined with a container image scanning tool such as Grype provides organizations with holistic security for their containerized environments. To learn more about Wazuh, check out our other blog posts and our ever-growing community.
References