Starting a VM as an unprivileged Linux User

Starting a VM as an unprivileged Linux User

How to run Docker-in-VM-in-Docker on Segfault's Servers

Sep 24, 2023·

3 min read

After reading this article you will be able to start any OS of any architecture from your (unprivileged) Linux shell (and log in as root to start (for example) Docker inside the emulated OS).

This is a great way to test or compile exploits and tools.

The instructions have been tested on Segfault's Disposable Root Servers.

First, we will boot an Ubuntu Linux x86_64, then an Ubuntu Linux aarch64 (arm64), then an Ubuntu Linux PowerPC (ppc64el) and lastly an OpenBSD x86_64.

Boot an AMD64 (x86_64) "Ubuntu 22.04 LTS Jammy"-Linux:

[[ -z $URL ]] && URL=""
[[ $ARCH =~ ^[0-9]*$ ]] && ARCH="x86_64" # No ARCH in name
apt-get install -y cloud-image-utils qemu-system
mkdir -p ~/.vm/"${OS}-${ARCH}" &>/dev/null && \
cd ~/.vm/"${OS}-${ARCH}" && \
cat >metadata.yaml <<-__EOF__
instance-id: iid-${SF_HOSTNAME:-THC}01
local-hostname: ${SF_HOSTNAME:-THC}-${OS}-${ARCH}-guest

Create an SSH key and configure the VM. The host's /sec directory will be shared with the VM:

[[ ! -f ~/.ssh/id_ed25519 ]] && ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519
cat >user-data.yaml <<-__EOF__
  - name: root
    lock_passwd: false
    # OpenBSD: hashed_passwd: '$2b$06$mbQdo90rertzSkoBBeZCzePTMtdkx7cuOax8xv.1W5ta0tJiNAlMG'
    hashed_passwd: '$(echo segfault | openssl passwd -6 -stdin)'
      - $(ssh-keygen -y -f ~/.ssh/id_ed25519)
  #FreeBSD: - sed -i "" 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config
  - mkdir -p /sec
  - [ host0, /sec, 9p ]
# Edit this file for OpenBSD or FreeBSD

Create the seed.img file (aka cloud-init) and download and enlarge the cloud image:

cloud-localds seed.img user-data.yaml metadata.yaml
[[ ! -f "${IMAGE:?}" ]] && wget "${URL}"
qemu-img resize "${IMAGE}" 32G

Boot the VM:

unset ARGS
[[ -e /dev/kvm ]] && ARGS+=("-enable-kvm")
[[ $ARCH == amd64 ]] && ARCH="x86_64"
[[ $ARCH == arm64 ]] && ARCH="aarch64"
[[ $ARCH == aarch64 ]] && ARGS=("-machine" "virt" "-bios" "/usr/share/qemu-efi-aarch64/QEMU_EFI.fd" "-cpu" "cortex-a57")
[[ $ARCH == ppc64el ]] && ARCH=ppc64le
[[ $ARCH == ppc64le ]] && unset ARGS
qemu-system-${ARCH} \
    -m 1G \
    -nographic \
    "${ARGS[@]}" \
    -device virtio-net-pci,netdev=net0 \
    -netdev user,id=net0,hostfwd=tcp::2222-:22 \
    -drive "if=virtio,format=qcow2,file=${IMAGE}" \
    -drive "if=virtio,format=raw,file=seed.img" \
    -virtfs local,path=/sec,mount_tag=host0,security_model=passthrough

The Linux Kernel will boot and you can log in with root / segfault or with ssh -p 2222 root@0:

Optional: Install and run an Alpine Linux inside Docker (inside the guest VM):

sudo bash
bash -c "$(curl -fsSL"
docker run --rm -it alpine

Set the URL= to a different location to start any other OS of any architecture. Examples:

# Ubuntu ARM64 (aarch64)
# Ubuntu PowerPC-64
# OpenBSD x86_64
# FreeBSD x86_64


  1. For OpenBSD, edit user-data.yaml and change:
    hashed_passwd: '$2b$06$mbQdo90rertzSkoBBeZCzePTMtdkx7cuOax8xv.1W5ta0tJiNAlMG'

  2. For FreeBSD, edit user-data.yaml and change:

    sed -i "" 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config

Other Cloud Servers:



Go all the way down the rabbit hole and read about cross-compiling exploits. Or read how to Start a User-Mode-Linux.

Shoutz to crt, MRX7014, Matthew and Ray San.