Home

Awesome

Container Explorer

Container Explorer (container-explorer) is a tool to explore containers of a disk image. Container Explorer supports exploring containers managed using containerd and docker container runtimes. Container Explorer attempts to provide the familiar output generated by tools like ctr and docker.

Container Explorer provides the following functionalities:

You can build the Container Explorer using the instruction at Build Container Explorer.

If you don't want to build, the binaries are available on https://github.com/google/container-explorer/releases.

Usage

The figure below shows the output of the container-explorer --help command.

NAME:
   container-explorer - A standalone utility to explore container details

USAGE:
   ce [global options] command [command options] [arguments...]

VERSION:
   0.2.1 (20240502)

DESCRIPTION:
   A standalone utility to explore container details.

  Container explorer supports exploring containers managed using containerd and
  docker. The utility also supports exploring containers created and managed using
  Kubernetes.


COMMANDS:
   list, ls              Lists container related information
   info                  show internal information
   mount                 mount a container to a mount point
   mount-all, mount_all  mount all containers
   drift, diff           identifies container filesystem changes
   help, h               Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug                                   enable debug messages
   --containerd-root value, -c value         specify containerd root directory
   --image-root value, -i value              specify mount point for a disk image
   --metadata-file value, -m value           specify the path to containerd metadata file i.e. meta.db
   --snapshot-metadata-file value, -s value  specify the path to containerd snapshot metadata file i.e. metadata.db.
   --use-layer-cache                         attempt to use cached layers where layers are symlinks
   --layer-cache value                       cached layer folder within the snapshot root (default: "layers")
   --namespace value, -n value               specify container namespace (default: "default")
   --docker-managed                          specify docker manages standalone or Kubernetes containers
   --docker-root value                       specify docker root directory. This is only used with flag --docker-managed
   --support-container-data value            a yaml file containing information about support containers
   --output value                            output format in json, table. Default is table (default: "table")
   --output-file value, -o value             output file to save the content
   --help, -h                                show help
   --version, -v                             print the version

Container Explorer helps you explore containers on a mounted disk image. Let's assume we have a clone of the Google Kubernetes Engine (GKE) node attached on a forensic VM as /dev/sdb.

  1. List the disk partition table.

    sudo fdisk -l /dev/sdb
    

    The output of the fdisk command.

    Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: gpt
    Disk identifier: 7C818738-EDF0-B246-960D-0E7EE8655B06
    
    Device     Start      End  Sectors  Size Type
    /dev/sdb1  8704000 20971486 12267487  5.8G Linux filesystem
    /dev/sdb2    20480    53247    32768   16M ChromeOS kernel
    /dev/sdb3  4509696  8703999  4194304    2G ChromeOS root fs
    /dev/sdb4    53248    86015    32768   16M ChromeOS kernel
    /dev/sdb5   315392  4509695  4194304    2G ChromeOS root fs
    /dev/sdb6    16448    16448        1  512B ChromeOS kernel
    /dev/sdb7    16449    16449        1  512B ChromeOS root fs
    /dev/sdb8    86016   118783    32768   16M Linux filesystem
    /dev/sdb9    16450    16450        1  512B ChromeOS reserved
    /dev/sdb10   16451    16451        1  512B ChromeOS reserved
    /dev/sdb11      64    16447    16384    8M BIOS boot
    /dev/sdb12  249856   315391    65536   32M EFI System
    
  2. Mount the /dev/sdb1 as read-only disk on mount point /mnt/case.

    sudo mount -o ro,noload,noexec /dev/sdb1 /mnt/case
    
  3. Use container-explorer to explore the mounted image.

    sudo ce -i /mnt/case --support-container-data supportcontainer.yaml list containers
    
  4. Mount an individual container or all containers

    Mount a container to mount point /mnt/container.

    sudo ce -i /mnt/case –support-container-data supportcontainer.yaml -n k8s.io mount f3c910583a81e7441e2cbd209b72afa4740e676ff8d82f2c74fdc5c78e179c10 /container
    

    Mount all containers to mount point /mnt/container. Mounting all containers will create sub-directories using container ID as directory name.

    sudo ce -i /mnt/case –support-container-data supportcontainer.yaml mount-all /mnt/container
    
  5. List the mounted containers within /mnt/container/.

    sudo ls -l /mnt/container
    

    The output of the command.

    drwxr-xr-x 1 root root 4096 Feb  5 08:55 3544209cfda893703458d7d0a6a65970bfb46e9be6a60faa1e4e9d0adae11b55
    drwxr-xr-x 1 root root 4096 Feb  5 08:54 3646fe81507be0510e9191d7e34adbeb751e7ecd86f7e1657289968828c5c8e3
    drwxr-xr-x 1 root root 4096 Feb  5 08:54 68a04caa81f9a4265e53a83b50874faca5a7c8400ee0c064d40d81cde6f03b86
    drwxr-xr-x 1 root root 4096 Feb  5 09:14 6f68aeae9c0288c2412f793d3a7b85efac189786ed8da2bdce9f88d39827fb80
    drwxr-xr-x 1 root root 4096 Feb  5 08:55 7227972ec83761790a65c137239c48817a26b8ad85be74b1ecf751656a2a61be
    drwxr-xr-x 1 root root 4096 Feb  5 09:13 cc9bc4f6c6b35b8a3616d8b4586741d8dc148c62b394d276dfab7572ee5aa542
    drwxr-xr-x 1 root root 4096 Feb  5 09:13 d3d1ff8c4ef39acbdf0a44bee6c326786309e408942d6a2d42cbaa1661bac77f
    drwxr-xr-x 1 root root 4096 Feb  5 08:54 f3c910583a81e7441e2cbd209b72afa4740e676ff8d82f2c74fdc5c78e179c10
    
  6. See filesystem changes

    sudo ce -i /mnt/case/ --output json --support-container-data supportcontainer.yaml drift
    

    In order to see drift of a particular container, supply the container ID with drift/diff

    sudo ce -i /mnt/case/ --output json --support-container-data supportcontainer.yaml drift f3c910583a81e7441e2cbd209b72afa4740e676ff8d82f2c74fdc5c78e179c10
    
  7. Use your favorite forensic tool to process mounted containers.

Mounting Disk Image

Let's assume you have a GKE node disk image as clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img.

  1. List the partition table.

    sudo fdisk -l clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img
    

    The output of the fdisk -l command.

    Disk clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img: 10 GiB, 10737418240 bytes, 20971520 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: gpt
    Disk identifier: 7C818738-EDF0-B246-960D-0E7EE8655B06
    
    Device                                                  Start      End  Sectors  Size Type
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img1  8704000 20971486 12267487  5.8G Linux filesystem
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img2    20480    53247    32768   16M ChromeOS kernel
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img3  4509696  8703999  4194304    2G ChromeOS root fs
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img4    53248    86015    32768   16M ChromeOS kernel
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img5   315392  4509695  4194304    2G ChromeOS root fs
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img6    16448    16448        1  512B ChromeOS kernel
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img7    16449    16449        1  512B ChromeOS root fs
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img8    86016   118783    32768   16M Linux filesystem
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img9    16450    16450        1  512B ChromeOS reserved
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img10   16451    16451        1  512B ChromeOS reserved
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img11      64    16447    16384    8M BIOS boot
    clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img12  249856   315391    65536   32M EFI System
    
  2. Mount the first partition (Linux Filesystem)

    sudo mount -o ro,noload,noexec,offset=$((8704000*512)) clone-gke-wp-cluster-default-pool-b4e5d97b-btxm.img /mnt/case
    

Docker Containers

Container Explorer supports exploring Docker managed containers. Use --docker-managed global flag to explore Docker containers.

sudo ce -i /mnt/case --support-container-data supportcontainer.yaml --docker-managed list containers

Container Explorer supports the following operation on Docker containers:

Excluding Containers

When a GKE cluster is created, several containers are created to support the Kubernetes. These clusters are used to support Kubernetes only and may not be interesting for the investigation.

The Kubernetes support containers are hidden by default when the global flag --support-container-data=supportcontainer.yaml is used.

The supportcontainer.yaml contains the commonly known hostname, image, and labels used to identify the support containers.

When --support-container-data is used, the list and mount-all commands automatically ignores the known support containers where applicable. You can use --show-support-containers and --mount-support-containers to display and mount the support containers.

Filtering Containers

Container Explorer supports filtering containers using the labels. This is particularly handy while reviewing GKE containers. Filter supports comma separated key/value pairs. The filter --filter io.cri-containerd.kind=container lists containerd containers.

The command below shows containers in pod namespace default.

/opt/container-explorer/bin/ce -i /mnt list containers --filter io.cri-containerd.kind=container,io.kubernetes.pod.namespace=default

Installing Container Explorer

Follow the steps below to install a pre-compiled Container Explorer on Linux systems.

  1. Download setup script setup.sh which is located at https://github.com/google/container-explorer/blob/main/script/setup.sh

    wget https://raw.githubusercontent.com/google/container-explorer/main/script/setup.sh
    
  2. Run the script with root privileges.

    sudo bash setup.sh install
    

    Container Explorer files will be created at /opt/container-explorer

  3. Run Container Explorer

    /opt/container-explorer/bin/ce -h
    

    Note: supportcontainer.yaml is located at /opt/container-explorer/etc/supportcontainer.yaml

Build Container Explorer

Follow the steps below to compile the Container Explorer.

  1. Verify Golang version is 1.20 or above

    go version
    
  2. Clone Container Explorer github project

    git clone https://github.com/google/container-explorer
    
  3. Compile the code

    cd container-explorer
    go build -ldflags '-s -w' -o $HOME/ce cmd/main.go
    
  4. Run container-explorer

    $HOME/ce -h