Skip to content

Lab 13 โ€” Capstone: Build, Harden & Audit a Containerized System

Field Details
Course SCIA-360 OS Security
Topic Capstone โ€” All Chapters
Chapters Integrates Chapters 4, 5, 6, 8, 9, 12, 14
Difficulty โญโญโญ Advanced
Estimated Time 90โ€“120 minutes
Requires Docker, ubuntu:22.04 image, Python 3

Overview

This capstone lab integrates all major OS security concepts from SCIA-360 into a single hands-on scenario. You will:

  1. Build a containerized Ubuntu system that is deliberately misconfigured with six distinct vulnerabilities
  2. Assess the system using both manual inspection and automated audit techniques
  3. Harden the system by remediating each vulnerability in sequence
  4. Verify the improvements with a final automated audit and calculate a hardening score

Each vulnerability maps to a specific course chapter, reinforcing how the individual topics form a coherent, layered security posture. By the end of this lab you will have hands-on experience with the complete security engineering lifecycle: assess โ†’ remediate โ†’ verify.

Time Management

This lab has more steps than previous labs. Read each part fully before executing commands. Budget at least 90 minutes โ€” rushing through remediation steps without understanding them undermines the learning objective. The capstone essay is worth 30% of the grade and requires thoughtful reflection.


Vulnerability Summary

The insecure system you will build contains six deliberate vulnerabilities. Keep this table as your remediation checklist:

# Vulnerability Severity Chapter Fixed?
1 Container runs as root (no USER directive) High Ch.6 โ€” Capabilities โ˜
2 SUID bit on python3 High Ch.4 โ€” FS Security โ˜
3 World-writable /var/www/html (mode 777) High Ch.4 โ€” FS Security โ˜
4 SSH root login enabled Critical Ch.5 โ€” Authentication โ˜
5 Weak webapp user password (abc) Critical Ch.5 โ€” Authentication โ˜
6 IP forwarding enabled (default container behavior) Medium Ch.12 โ€” Linux Architecture โ˜

Part 1 โ€” Build the Insecure System

Step 1.1 โ€” Create the Dockerfile

Each # INSECURITY comment in the Dockerfile identifies a deliberate misconfiguration. Study these comments carefully โ€” you will reference them during assessment and remediation.

mkdir -p /tmp/scia360cap

cat > /tmp/scia360cap/Dockerfile << 'DEOF'
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive

# INSECURITY 1: No non-root USER directive โ€” container runs as root
# INSECURITY 2: Installs unnecessary services (attack surface)
RUN apt-get update -qq && apt-get install -y -qq nginx openssh-server python3 procps 2>/dev/null

# INSECURITY 3: Root SSH login enabled โ€” allows direct root brute-force
RUN mkdir -p /run/sshd && \
    sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
    echo 'root:password123' | chpasswd

# INSECURITY 4: World-writable web directory โ€” any user can modify web content
RUN chmod 777 /var/www/html

# INSECURITY 5: SUID on python3 โ€” trivial privilege escalation
RUN chmod u+s /usr/bin/python3.10 2>/dev/null || chmod u+s $(which python3) 2>/dev/null || true

# INSECURITY 6: Weak user password โ€” trivially crackable
RUN useradd -m -s /bin/bash webapp && echo 'webapp:abc' | chpasswd

EXPOSE 80 22
CMD ["/bin/bash", "-c", "service nginx start 2>/dev/null; /usr/sbin/sshd -D"]
DEOF

docker build -t insecure-os-lab /tmp/scia360cap/ 2>&1 | tail -5

Expected output:

...
Successfully built a1b2c3d4e5f6
Successfully tagged insecure-os-lab:latest

๐Ÿ“ธ Screenshot checkpoint 13a: Capture the Docker build success output showing the image tag.


Step 1.2 โ€” Start the insecure container

docker run -d --name insecure-system -p 8080:80 -p 2222:22 insecure-os-lab
sleep 3
docker ps | grep insecure

Expected output:

CONTAINER ID   IMAGE             COMMAND      ...   PORTS
a1b2c3d4e5f6   insecure-os-lab   "/bin/bash..." ...   0.0.0.0:8080->80/tcp, 0.0.0.0:2222->22/tcp

The container is now running with two exposed ports: nginx on 8080 and SSH on 2222. Both services run as root inside the container.

๐Ÿ“ธ Screenshot checkpoint 13b-start: Capture docker ps output confirming the container is running with the exposed ports.


Part 2 โ€” Security Assessment

A systematic security assessment examines the running system across all vulnerability categories. The goal is to document every finding before touching anything โ€” changes during an assessment can destroy forensic evidence or mask related vulnerabilities.

Step 2.1 โ€” Initial audit

docker exec insecure-system bash -c "
echo '=== 1. Process user ==='
id

echo '=== 2. SUID binaries (unexpected) ==='
find / -perm -4000 -type f 2>/dev/null | grep -v proc | grep -v '/usr/bin/passwd\|/usr/bin/su\|/usr/bin/mount\|/usr/bin/umount\|/usr/bin/newgrp\|/usr/bin/chsh\|/usr/bin/gpasswd\|/usr/bin/chfn'

echo '=== 3. World-writable dirs ==='
find /var/www -perm -0002 -type d 2>/dev/null

echo '=== 4. SSH root login ==='
grep PermitRootLogin /etc/ssh/sshd_config | grep -v '^#'

echo '=== 5. Weak password (webapp:abc hashed) ==='
grep webapp /etc/shadow | cut -d: -f2 | cut -c1-6

echo '=== 6. IP forwarding ==='
cat /proc/sys/net/ipv4/ip_forward

echo '=== 7. Network exposure ==='
ss -tlnp 2>/dev/null"

Expected output (all vulnerabilities visible):

=== 1. Process user ===
uid=0(root) gid=0(root) groups=0(root)    โ† running as root

=== 2. SUID binaries (unexpected) ===
/usr/bin/python3.10                        โ† SUID python3!

=== 3. World-writable dirs ===
/var/www/html                              โ† world-writable

=== 4. SSH root login ===
PermitRootLogin yes                        โ† root SSH enabled

=== 5. Weak password (webapp:abc hashed) ===
$y$j9T                                     โ† short hash prefix

=== 6. IP forwarding ===
1                                          โ† forwarding enabled

=== 7. Network exposure ===
tcp  LISTEN  0.0.0.0:80   sshd, nginx...  โ† both services exposed

๐Ÿ“ธ Screenshot checkpoint 13b: Capture the complete initial audit output showing all six vulnerability categories.


Part 3 โ€” Apply Hardening

Remediate each vulnerability in sequence. After each fix, mark it off in your vulnerability table.

Step 3.1 โ€” Vulnerability #2: Remove SUID from python3

A SUID python3 is a complete privilege escalation bypass โ€” anyone who can run python3 can trivially execute arbitrary code as root:

python3 -c "import os; os.setuid(0); os.system('/bin/bash')"
docker exec insecure-system bash -c "
find /usr/bin -name 'python3*' -perm -4000 2>/dev/null
find /usr/bin -name 'python3*' -perm -4000 -exec chmod u-s {} \; 2>/dev/null
find /usr/bin -name 'python3*' -perm -4000 2>/dev/null || echo 'SUID removed from python3'"

Expected output:

/usr/bin/python3.10        โ† found before
SUID removed from python3  โ† gone after

๐Ÿ“ธ Screenshot checkpoint 13c: Capture the before (python3 found) and after (SUID removed) output.


Step 3.2 โ€” Vulnerability #3: Fix world-writable web directory

A world-writable web root (chmod 777) allows any process running on the server โ€” regardless of user โ€” to modify, replace, or delete web content. This enables web defacement and malicious file injection.

docker exec insecure-system bash -c "
ls -la /var/www/
chmod 755 /var/www/html
ls -la /var/www/"

Expected output:

drwxrwxrwx 2 root root 4096 ... html    โ† world-writable before
drwxr-xr-x 2 root root 4096 ... html    โ† 755 after (owner write only)

๐Ÿ“ธ Screenshot checkpoint 13d: Capture the ls -la /var/www/ output before (777) and after (755).


Step 3.3 โ€” Vulnerability #4: Disable SSH root login

Allowing root to log in directly via SSH eliminates one layer of protection. Best practice is to require users to log in as themselves and then sudo โ€” creating an audit trail of who performed which privileged actions.

docker exec insecure-system bash -c "
grep PermitRootLogin /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
grep PermitRootLogin /etc/ssh/sshd_config
kill -HUP \$(pgrep -f 'sshd -D') 2>/dev/null && echo 'SSH config reloaded'"

Expected output:

PermitRootLogin yes            โ† before
PermitRootLogin no             โ† after
SSH config reloaded

๐Ÿ“ธ Screenshot checkpoint 13e: Capture both grep PermitRootLogin outputs and the "SSH config reloaded" confirmation.


Step 3.4 โ€” Vulnerability #5: Strengthen the webapp password

The password abc is a single dictionary word that would be cracked in milliseconds by any password cracking tool. A strong password should be 12+ characters, mixing uppercase, lowercase, numbers, and symbols.

docker exec insecure-system bash -c "
echo 'webapp:Str0ng!P@ssw0rd99' | chpasswd
grep webapp /etc/shadow | cut -d: -f2 | cut -c1-8
echo 'Password strengthened'"

Expected output:

$y$j9T$L     โ† longer, more complex hash prefix confirms new password
Password strengthened

๐Ÿ“ธ Screenshot checkpoint 13f-password: Capture the hash prefix change confirming the password update.


Step 3.5 โ€” Vulnerability #6: Network hardening

Disable IP forwarding and ICMP redirects per CIS controls 3.2.1โ€“3.2.3, and enable martian packet logging as an additional detection control:

docker exec insecure-system bash -c "
echo 0 > /proc/sys/net/ipv4/ip_forward
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 1 > /proc/sys/net/ipv4/conf/all/log_martians
echo 'Network hardened:'
echo 'ip_forward:' && cat /proc/sys/net/ipv4/ip_forward
echo 'accept_redirects:' && cat /proc/sys/net/ipv4/conf/all/accept_redirects"

Expected output:

Network hardened:
ip_forward: 0
accept_redirects: 0

๐Ÿ“ธ Screenshot checkpoint 13f: Capture all network parameter values after hardening.


Part 4 โ€” Post-Hardening Audit

Step 4.1 โ€” Final automated verification

Run the final audit script to measure the outcome of your hardening work. This produces a quantitative hardening score.

docker exec insecure-system python3 -c "
import os, subprocess, stat

checks = []
def check(name, passed, detail=''):
    checks.append(passed)
    print(f'{chr(9989) if passed else chr(10060)}  {name}' + (f' ({detail})' if detail else ''))

# 1. SUID python3 removed
r = subprocess.run(['find','/usr/bin','-name','python3*','-perm','-4000'], capture_output=True, text=True)
check('SUID python3 removed', not r.stdout.strip(), r.stdout.strip()[:40] or 'none found')

# 2. Web dir not world-writable
st = os.stat('/var/www/html')
check('/var/www/html not world-writable', not bool(st.st_mode & stat.S_IWOTH), oct(stat.S_IMODE(st.st_mode)))

# 3. SSH root disabled
r = subprocess.run(['grep','PermitRootLogin','/etc/ssh/sshd_config'], capture_output=True, text=True)
check('SSH root login disabled', 'no' in r.stdout.lower(), r.stdout.strip())

# 4. IP forwarding off
fwd = open('/proc/sys/net/ipv4/ip_forward').read().strip()
check('IP forwarding disabled', fwd == '0', fwd)

# 5. ICMP redirects off
redir = open('/proc/sys/net/ipv4/conf/all/accept_redirects').read().strip()
check('ICMP redirects disabled', redir == '0', redir)

# 6. /tmp sticky bit
check('/tmp sticky bit', bool(os.stat('/tmp').st_mode & stat.S_ISVTX))

# 7. /etc/passwd permissions
check('/etc/passwd perms 644', oct(stat.S_IMODE(os.stat('/etc/passwd').st_mode)) == '0o644')

passed = sum(checks)
print(f'\nFinal: {passed}/{len(checks)} checks passed')
print(f'Hardening score: {int(passed/len(checks)*100)}/100')
"

Expected output after hardening:

โœ…  SUID python3 removed (none found)
โœ…  /var/www/html not world-writable (0o755)
โœ…  SSH root login disabled (PermitRootLogin no)
โœ…  IP forwarding disabled (0)
โœ…  ICMP redirects disabled (0)
โœ…  /tmp sticky bit
โœ…  /etc/passwd perms 644

Final: 7/7 checks passed
Hardening score: 100/100

๐Ÿ“ธ Screenshot checkpoint 13g: Capture the final audit output showing all checks passed and the hardening score.


Step 4.2 โ€” Cleanup

docker stop insecure-system && docker rm insecure-system
docker rmi insecure-os-lab
rm -rf /tmp/scia360cap
docker system prune -f

Assessment

Screenshot Checklist

ID Description Points
13a Docker build success with image tag 3
13b Initial audit showing all 6+ vulnerability categories 6
13c SUID removed from python3 (before and after) 4
13d /var/www/html permission fixed (777 โ†’ 755) 4
13e PermitRootLogin changed from yes to no 4
13f Network parameters hardened (ip_forward, accept_redirects = 0) 4
13g Final audit with score (ideally 100/100) 5
Screenshot subtotal 30

Grading Rubric

Component Points
Screenshots + vulnerability table (complete all 6 rows) 30
Hardening correctly applied (verified by instructor replication) 20
Final audit score (pro-rated: 100/100 = 20pts, 85/100 = 17pts, etc.) 20
Final reflection essay (400โ€“500 words, all 4 prompts addressed) 30
Total 100

Vulnerability Table (complete and submit)

Complete the "Fixed?" column and add a one-sentence explanation of how each fix reduces risk:

# Vulnerability Severity Chapter Fixed? How the Fix Reduces Risk
1 Runs as root (no USER directive) High Ch.6 Capabilities โ˜
2 SUID python3 High Ch.4 FS Security โ˜
3 World-writable /var/www/html High Ch.4 FS Security โ˜
4 SSH root login enabled Critical Ch.5 Authentication โ˜
5 Weak webapp password (abc) Critical Ch.5 Authentication โ˜
6 IP forwarding enabled Medium Ch.12 Linux Architecture โ˜

Final Reflection Essay

Write a 400โ€“500 word essay addressing all four of the following prompts. This essay demonstrates your ability to synthesize SCIA-360 concepts rather than simply execute commands.


Prompt 1 โ€” Vulnerability Ranking

Rank the six vulnerabilities from most to least severe and justify your ranking. Consider: which vulnerability is most likely to be discovered and exploited by an external attacker with no prior access? Which vulnerability would cause the greatest damage if exploited? Which single remediation provides the biggest security improvement per effort invested?


Prompt 2 โ€” Defense in Depth

Describe how the OS security concepts from SCIA-360 โ€” namespaces, capabilities, seccomp, file permissions, authentication hardening, and logging โ€” work together as complementary layers of defense. Define defense in depth as a security architecture principle. Explain why a single strong control (e.g., "the container is behind a firewall") is insufficient if inner layers are misconfigured, using the vulnerabilities in this lab as examples.


Prompt 3 โ€” Hardened Docker Run Command

This container currently runs with default Docker security settings and as the root user inside the container. Using the Docker security options below, write a complete hardened docker run command that would significantly reduce the attack surface. Briefly explain what each option does.

Options to use (minimum โ€” use all of them):

Option Purpose
--user 1000:1000 Run as non-root user
--cap-drop ALL Drop all Linux capabilities
--cap-add NET_BIND_SERVICE Re-add only what nginx needs
--read-only Mount root filesystem read-only
--tmpfs /tmp:rw,nosuid,noexec Writable tmp without SUID/exec
--security-opt no-new-privileges Prevent privilege escalation
--security-opt seccomp=/path/to/profile.json Restrict system calls

Prompt 4 โ€” Professional Recommendations

You have been hired as a security consultant by a startup that is deploying their first containerized web application to AWS. Based on everything you learned in SCIA-360, provide your top three OS-level security recommendations for their deployment. For each recommendation:

  • State the recommendation clearly
  • Explain the threat it mitigates
  • Describe how they would implement it
  • Identify one metric or check they could use to verify compliance

Your recommendations should reflect real-world priorities โ€” things a reasonable security budget and engineering team can actually accomplish โ€” not a wish list of perfect security.


Essay Grading Criteria

Criterion Description Points
Completeness All four prompts addressed with sufficient depth 10
Technical accuracy Concepts correctly explained with appropriate terminology 10
Synthesis Demonstrates integration of SCIA-360 topics rather than isolated recall 5
Professionalism Clear writing, logical structure, appropriate length (400โ€“500 words) 5
Total essay 30