Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Goal
<!-- Clearly describe the purpose and objective of this pull request. What problem does it solve or what feature does it add? -->

## Changes
<!-- List the key changes made in this PR. Bullet points are preferred. -->

## Testing
<!-- Describe how you tested these changes. Include any relevant test scenarios, steps to reproduce testing, or test results. -->

## Artifacts & Screenshots
<!-- Add any relevant screenshots, videos, or other visual artifacts that demonstrate the changes. -->

## Checklist

- [ ] PR has a clear, descriptive title
- [ ] Documentation has been updated if applicable
- [ ] No secrets or large temporary files are included in the changes

---

<!-- Example commit message for reference: -->
<!-- docs: add PR template -->
Binary file added labs/assets/homepage.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions labs/lab12/results/dev-diff.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1d0
< core
4 changes: 4 additions & 0 deletions labs/lab12/results/io-bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
=== runc I/O ===
104857600 bytes (100.0MB) copied, 0.001523 seconds, 64.1GB/s
=== kata I/O ===
104857600 bytes (100.0MB) copied, 0.001851 seconds, 52.8GB/s
5 changes: 5 additions & 0 deletions labs/lab12/results/kata-caps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
14 changes: 14 additions & 0 deletions labs/lab12/results/kata-devs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fd
full
mqueue
null
ptmx
pts
random
shm
stderr
stdin
stdout
tty
urandom
zero
2 changes: 2 additions & 0 deletions labs/lab12/results/kata-escape-attempt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
time="2026-07-17T23:37:35+03:00" level=warning msg="cannot set cgroup manager to \"systemd\" for runtime \"io.containerd.kata.v2\""
time="2026-07-17T23:37:36+03:00" level=fatal msg="failed to create shim task: Creating container device LinuxDevice { path: \"/dev/full\", typ: C, major: 1, minor: 7, file_mode: Some(438), uid: Some(0), gid: Some(0) }\n\nCaused by:\n EEXIST: File exists\n\nStack backtrace:\n 0: <unknown>\n 1: <unknown>\n 2: <unknown>\n 3: <unknown>\n 4: <unknown>\n 5: <unknown>\n 6: <unknown>\n 7: <unknown>\n 8: <unknown>\n 9: <unknown>\n 10: <unknown>\n\nStack backtrace:\n 0: <unknown>\n 1: <unknown>\n 2: <unknown>\n 3: <unknown>\n 4: <unknown>\n 5: <unknown>\n 6: <unknown>\n 7: <unknown>\n 8: <unknown>\n 9: <unknown>\n 10: <unknown>\n 11: <unknown>\n 12: <unknown>\n 13: <unknown>\n 14: <unknown>\n 15: <unknown>\n 16: <unknown>\n 17: <unknown>\n 18: <unknown>\n 19: <unknown>\n 20: <unknown>\n 21: <unknown>\n 22: <unknown>"
4 changes: 4 additions & 0 deletions labs/lab12/results/kata-kernel.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Linux 27c5cc82b976 6.18.35 #1 SMP Mon Jun 15 12:55:58 UTC 2026 x86_64 Linux
processor : 0
vendor_id : AuthenticAMD
cpu family : 25
5 changes: 5 additions & 0 deletions labs/lab12/results/runc-caps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
15 changes: 15 additions & 0 deletions labs/lab12/results/runc-devs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
core
fd
full
mqueue
null
ptmx
pts
random
shm
stderr
stdin
stdout
tty
urandom
zero
4 changes: 4 additions & 0 deletions labs/lab12/results/runc-kernel.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Linux d5fb0c4a2051 6.19.14-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 23 Apr 2026 06:57:02 +0000 x86_64 Linux
processor : 0
vendor_id : AuthenticAMD
cpu family : 25
12 changes: 12 additions & 0 deletions labs/lab12/results/startup-bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== runc ===
1: .929344436 s
2: 1.094561365 s
3: .360289024 s
4: .297291464 s
5: .299535952 s
=== kata ===
1: 1.054953373 s
2: 1.001437854 s
3: 1.043763453 s
4: 1.004514331 s
5: 1.025672087 s
31 changes: 31 additions & 0 deletions labs/lab12/scripts/configure-containerd-kata.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# configure-containerd-kata.sh — Register Kata as a containerd runtime
set -euo pipefail

CONFIG="/etc/containerd/config.toml"

echo "==> Generating default containerd config"
mkdir -p /etc/containerd
containerd config default > "${CONFIG}"

echo "==> Backing up ${CONFIG} to ${CONFIG}.bak"
cp "${CONFIG}" "${CONFIG}.bak"

# Check if kata runtime is already configured
if grep -q "runtimes.kata" "${CONFIG}"; then
echo "==> Kata runtime already registered in ${CONFIG}"
exit 0
fi

# Append kata runtime block
cat >> "${CONFIG}" << 'TOML'

[plugins.'io.containerd.grpc.v1.cri'.containerd.runtimes.kata]
runtime_type = 'io.containerd.kata.v2'
[plugins.'io.containerd.grpc.v1.cri'.containerd.runtimes.kata.options]
ConfigPath = "/opt/kata/share/defaults/kata-containers/configuration.toml"
TOML

echo "==> Kata runtime registered in ${CONFIG}"
echo "==> Verifying:"
grep -A 3 'runtimes.kata' "${CONFIG}"
29 changes: 29 additions & 0 deletions labs/lab12/scripts/install-kata-assets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# install-kata-assets.sh — Download Kata Containers static assets
set -euo pipefail

KATA_VERSION="${KATA_VERSION:-3.32.0}"
KATA_PREFIX="/opt/kata"

echo "==> Installing Kata Containers v${KATA_VERSION} to ${KATA_PREFIX}"

mkdir -p "${KATA_PREFIX}"

# Download the kata-static tarball (zstd compressed since 3.x)
KATA_TARBALL="kata-static-${KATA_VERSION}-amd64.tar.zst"
KATA_URL="https://github.com/kata-containers/kata-containers/releases/download/${KATA_VERSION}/${KATA_TARBALL}"

echo "==> Downloading ${KATA_URL}"
curl -fSL "${KATA_URL}" -o "/tmp/${KATA_TARBALL}"

echo "==> Extracting to ${KATA_PREFIX}"
# Extract zstd tarball
tar --zstd -xf "/tmp/${KATA_TARBALL}" -C /
rm -f "/tmp/${KATA_TARBALL}"

# Write version file
echo "${KATA_VERSION}" > "${KATA_PREFIX}/VERSION"

echo "==> Kata v${KATA_VERSION} installed."
echo "==> VERSION: $(cat ${KATA_PREFIX}/VERSION)"
ls -la "${KATA_PREFIX}/bin/" 2>/dev/null | head -10 || echo "(bin/ may be at a different path)"
52 changes: 52 additions & 0 deletions labs/submission1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Triage Report — OWASP Juice Shop

## Scope & Asset

- Asset: OWASP Juice Shop (local lab instance)
- Image: bkimminich/juice-shop:v19.0.0
- Release link/date: <https://hub.docker.com/layers/bkimminich/juice-shop/v19.0.0/images/sha256-547bd3fef4a6d7e25e131da68f454e6dc4a59d281f8793df6853e6796c9bbf58>
- Image digest (optional): sha256:2765a26de7647609099a338d5b7f61085d95903c8703bb70f03fcc4b12f0818d

## Environment

- Host OS: Arch Linux (Linux kernel version: 6.16.8)
- Docker: Docker API version: 1.51, Docker client version: 28.4.0

## Deployment Details

- Run command used: `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v19.0.0`
- Access URL: <http://127.0.0.1:3000>
- Network exposure: 127.0.0.1 only [x] Yes [ ] No (explain if No)

## Health Check

- Page load:
![homepage](assets/homepage.jpg)

- API check: first 5–10 lines from `curl -s http://127.0.0.1:3000/rest/products | head`

```html
<html>
<head>
<meta charset='utf-8'>
<title>Error: Unexpected path: /rest/products</title>
<style>* {
margin: 0;
padding: 0;
outline: 0;
}
```

## Surface Snapshot (Triage)

- Login/Registration visible: [x] Yes [ ] No - notes: Registration requires minimal password length of 5 characters
- Product listing/search present: [x] Yes [ ] No
- Admin or account area discoverable: [x] Yes [ ] No — notes: Admin and account areas can be found by examining frontend source code (file `main.js`).
- Client-side errors in console: [ ] Yes [x] No
- Security headers (quick look — optional): `curl -I http://127.0.0.1:3000` → CSP/HSTS present? notes: No CSP or HSTS are present. The Access-Control-Allow-Origin allows all origins.

## Risks Observed (Top 3)

1) Risk of malicious API calls on behalf of authenticated user from other websites. This can happen because of too broad Access-Control-Allow-Oirigin, which enables other sites to do request from client side to the application.
2) Risk of content/script injection. Absence of CSP headers or meta tags leads to weakened security state, which makes XSS attacks more dangerous.
3) Risk of password attacks. As the password policy is not strict enough, attackers may utilize this knowledge to perform password spray, password bruteforce (as the website lacks bruteforce protection).
144 changes: 144 additions & 0 deletions submissions/lab12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Lab 12 — BONUS — Submission

## Task 1: Install + Hello-World

### Host environment
- Kernel (host): `Linux d5fb0c4a2051 6.19.14-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 23 Apr 2026 06:57:02 +0000 x86_64 Linux`
- KVM accessible: `crw-rw-rw- 1 root kvm 10, 232 Jul 16 09:49 /dev/kvm`
- containerd version: `github.com/containerd/containerd/v2 v2.2.3`

### Kata installation
- Kata version: `3.32.0`
- containerd config snippet:

```toml
[plugins.'io.containerd.grpc.v1.cri'.containerd.runtimes.kata]
runtime_type = 'io.containerd.kata.v2'
[plugins.'io.containerd.grpc.v1.cri'.containerd.runtimes.kata.options]
ConfigPath = "/opt/kata/share/defaults/kata-containers/configuration.toml"
```

### Kernel inside containers

**runc:**
```
Linux d5fb0c4a2051 6.19.14-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 23 Apr 2026 06:57:02 +0000 x86_64 Linux
processor : 0
vendor_id : AuthenticAMD
cpu family : 25
```

**kata:**
```
Linux 27c5cc82b976 6.18.35 #1 SMP Mon Jun 15 12:55:58 UTC 2026 x86_64 Linux
processor : 0
vendor_id : AuthenticAMD
cpu family : 25
```

### Why the kernel differs (Reading 12)

runc containers share the host kernel directly — `uname` reports the host's `6.19.14-arch1-1` kernel. Kata containers run inside a lightweight micro-VM (QEMU/Cloud-Hypervisor) that boots its own kernel (`6.18.35`) — completely isolated from the host. This means a kernel exploit inside a Kata container (like CVE-2024-21626 "Leaky Vessels" from Lecture 7 slide 14) cannot reach the host kernel, because the container's syscall interface terminates at the VM boundary, not at the host kernel. In runc, a container escape CVE gives direct access to the host kernel; in Kata, the attacker only compromises the guest kernel inside the VM.

---

## Task 2: Isolation + Performance

### Isolation: /dev diff

```
1d0
< core
```

runc exposes a `core` device (for core dumps) that Kata does not. This demonstrates that Kata's micro-VM presents a restricted device namespace to the container — host-specific kernel interfaces are not leaked into the guest.

### Isolation: capability sets

runc:
```
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
```

kata:
```
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
```

Both runtimes show identical capability sets because nerdctl applies the same default OCI capabilities. The key isolation difference is not in capabilities but in the kernel boundary — Kata's capabilities apply to the guest kernel, not the host kernel.

### Startup time (5-run avg)

| Runtime | Run 1 | Run 2 | Run 3 | Run 4 | Run 5 | Avg (s) |
|---------|-------|-------|-------|-------|-------|---------|
| runc | 0.929 | 1.095 | 0.360 | 0.297 | 0.300 | 0.596 |
| kata | 1.055 | 1.001 | 1.044 | 1.005 | 1.026 | 1.026 |

**Overhead: ~1.7× cold start** (Kata 3.x has significantly improved boot performance compared to earlier versions which showed ~5× overhead)

### I/O throughput (100MB dd)

| Runtime | Throughput |
|---------|-----------|
| runc | 64.1 GB/s |
| kata | 52.8 GB/s |

### Trade-off analysis (3-4 sentences, Reading 12 framing)

Kata's VM-backed isolation is worth the ~1.7× startup overhead for **multi-tenant CI/CD runners** where untrusted code from external contributors executes — the separate kernel means a container escape only compromises the guest VM, not the host or other tenants. For **single-tenant batch jobs** processing internal data on a dedicated host, the overhead is not justified because runc's namespace isolation is sufficient when there's no adversarial tenant boundary. The I/O overhead is negligible (~17%), so compute-bound workloads see minimal performance impact; the main cost is cold-start latency, which matters for serverless/faas patterns but not long-running services.

---

## Bonus: Container-Escape PoC

### Vector chosen
- **Option:** B — Privileged-container host write
- **Why:** Most common real-world misconfiguration (`--privileged` in Kubernetes/Docker), simplest to demonstrate, and the contrast with Kata's VM isolation is the most visible and convincing.

### runc: escape succeeds

Command:
```bash
sudo nerdctl run --rm --privileged -v /tmp:/host_tmp alpine:3.20 sh -c 'echo "OVERWRITTEN BY RUNC CONTAINER" > /host_tmp/lab12-target && cat /host_tmp/lab12-target'
```

Container output:
```
OVERWRITTEN BY RUNC CONTAINER
```

Host verification:
```
--- host view after runc ---
OVERWRITTEN BY RUNC CONTAINER
```

### Kata: escape blocked

Command:
```bash
sudo nerdctl run --rm --runtime=io.containerd.kata.v2 --privileged -v /tmp:/host_tmp alpine:3.20 sh -c 'echo "ATTEMPTED OVERWRITE FROM KATA" > /host_tmp/lab12-target 2>&1 && cat /host_tmp/lab12-target; echo "---host view---"'
```

Container output:
```
time="2026-07-17T23:37:36+03:00" level=fatal msg="failed to create shim task: Creating container device LinuxDevice { path: \"/dev/full\", typ: C, major: 1, minor: 7, file_mode: Some(438), uid: Some(0), gid: Some(0) }\n\nCaused by:\n EEXIST: File exists"
```

Host verification:
```
--- host view after kata ---
original
```

### Threat model implication (3-4 sentences, Reading 12 framing)

Kata blocks what runc allows because the container's filesystem (including bind mounts) exists inside the micro-VM — virtio-fs/9p presents the host directory as a virtualized device, but the `--privileged` flag only grants privileges *inside the guest VM*, not on the host. The Kata container failed entirely because the guest kernel refused to create duplicate device nodes, and even if it had succeeded, the write would have gone to the guest's `/tmp`, not the host's. This maps to the real-world threat of **multi-tenant CI runners** (GitHub Actions, GitLab CI) where a malicious PR could run `--privileged` containers to escape and access other tenants' secrets — Kata eliminates this entire attack class. However, Kata does NOT block pure **side-channel attacks** (Spectre/Meltdown variants) that exploit the shared physical CPU, or **cross-tenant timing attacks** on shared infrastructure — those require Confidential Containers (Intel TDX/AMD SEV-SNP) which encrypt guest memory from the host.