CKS — Platform Binary Verification
Exam Context
| Property | Value |
|---|---|
| Domain | Domain 1 — Cluster Setup |
| Weight | 10% |
| Objective | Verify platform binaries before deploying |
Binary verification ensures that the Kubernetes components running in your cluster are authentic and untampered. If an attacker substitutes a modified kubectl, kubeadm, or kubelet binary, they can compromise your entire cluster without triggering any Kubernetes-native security controls.
Why Binary Verification Matters — Supply Chain Security
Threat Model
| Attack | Description | Impact |
|---|---|---|
| Tampered binary | Attacker replaces kubelet with a backdoored version | Full node compromise — the attacker’s code runs as root on every node |
| Man-in-the-middle download | HTTP download intercepted, binary replaced in transit | Modified binary with embedded backdoor |
| Compromised mirror | Unofficial download source serves malicious binary | Cluster-wide compromise if used for installation |
| Insider threat | Admin replaces binaries on existing nodes | Persistent backdoor survives cluster upgrades |
Real-World Context
- SolarWinds (2020): Attackers modified build artifacts to include a backdoor. The tampered binaries had valid signatures because they were injected during the build process.
- Codecov (2021): CI/CD script modified to exfiltrate credentials. Supply chain attacks are increasingly targeting infrastructure tools.
- Kubernetes itself: In 2020, a vulnerability (CVE-2020-8554) highlighted how MITM attacks could compromise cluster communication — verifying binaries at install time prevents one vector.
CKS perspective: The exam tests your ability to verify binaries using checksums. This is straightforward if you know the commands.
Official Download Source
Kubernetes binaries should only be downloaded from the official source:
| Resource | URL |
|---|---|
| Release page | https://dl.k8s.io |
| GitHub releases | https://github.com/kubernetes/kubernetes/releases |
| Changelog | https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/ |
| SHA checksums | Available alongside each binary on the release page |
Never download Kubernetes binaries from:
- Unofficial mirrors
- Third-party package managers (unless verified)
- HTTP URLs (always use HTTPS)
- Direct links from untrusted documentation
Step-by-Step: Binary Verification
Step 1: Determine the Required Version
# Check existing kubectl version
kubectl version --client --short 2>/dev/null || kubectl version --client
Expected output:
Client Version: v1.29.2
Step 2: Download the Binary
# Download kubectl for Linux amd64
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubectl"
Step 3: Download the Checksum File
# Download the sha256sum for kubectl
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubectl.sha256"
Step 4: Verify with sha256sum
# Verify the binary matches the checksum
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
Expected output (valid binary):
kubectl: OK
If the binary is tampered:
kubectl: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
Alternative: Manual Comparison
# Compute the hash of the downloaded binary
sha256sum kubectl
# Compare with the official checksum
cat kubectl.sha256
You visually compare the two hashes. They must be identical.
Step 5: Install the Verified Binary
# Make executable and move to PATH
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Verify installation
kubectl version --client
Verifying kubeadm and kubelet
The same process applies to all Kubernetes binaries.
kubeadm Verification
# Download kubeadm
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubeadm"
# Download checksum
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubeadm.sha256"
# Verify
echo "$(cat kubeadm.sha256) kubeadm" | sha256sum --check
Expected output:
kubeadm: OK
kubelet Verification
# Download kubelet
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubelet"
# Download checksum
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubelet.sha256"
# Verify
echo "$(cat kubelet.sha256) kubelet" | sha256sum --check
Expected output:
kubelet: OK
Using sha512sum
Some environments or exam scenarios may require sha512sum instead of sha256sum. The process is identical:
# Compute sha512 hash of a binary
sha512sum kubectl
Expected output:
a1b2c3d4e5f6... kubectl
# If you have a sha512 checksum file
echo "<expected-hash> kubectl" | sha512sum --check
Exam tip: The CKS exam may provide you with a sha512 hash and ask you to verify. The key commands are sha256sum and sha512sum with the --check flag.
Verifying Binaries Already Installed on Nodes
In a CKS exam scenario, you might need to verify that binaries on an existing node haven’t been tampered with.
Step 1: Find the Installed Binary
# Find kubectl location
which kubectl
# /usr/local/bin/kubectl
# Find kubelet location
which kubelet
# /usr/bin/kubelet
# Find kubeadm location
which kubeadm
# /usr/bin/kubeadm
Step 2: Check the Version
kubectl version --client
kubelet --version
kubeadm version
Step 3: Download the Official Binary for That Version
# Get kubelet version
KUBELET_VERSION=$(kubelet --version | awk '{print $2}')
echo $KUBELET_VERSION
# v1.29.2
# Download the official binary
curl -LO "https://dl.k8s.io/release/${KUBELET_VERSION}/bin/linux/amd64/kubelet"
# Download checksum
curl -LO "https://dl.k8s.io/release/${KUBELET_VERSION}/bin/linux/amd64/kubelet.sha256"
Step 4: Compare Hashes
# Hash of the installed binary
sha256sum /usr/bin/kubelet
# Hash of the official download
sha256sum kubelet
# Or compare directly
diff <(sha256sum /usr/bin/kubelet | awk '{print $1}') \
<(sha256sum kubelet | awk '{print $1}')
If diff produces no output, the hashes match — the installed binary is authentic.
If diff shows a difference:
1c1
< a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
---
> 9f8e7d6c5b4a9f8e7d6c5b4a9f8e7d6c5b4a9f8e7d6c5b4a9f8e7d6c5b4a9f8e
The binary has been tampered with. Replace it immediately with the verified official version.
Detecting Tampered Binaries
Automated Verification Script
#!/bin/bash
# verify-k8s-binaries.sh — Verify all Kubernetes binaries on a node
BINARIES=("kubectl" "kubelet" "kubeadm")
ARCH="linux/amd64"
FAILED=0
for BINARY in "${BINARIES[@]}"; do
INSTALLED_PATH=$(which "$BINARY" 2>/dev/null)
if [[ -z "$INSTALLED_PATH" ]]; then
echo "[SKIP] $BINARY not found"
continue
fi
# Get installed version
case "$BINARY" in
kubectl) VERSION=$(kubectl version --client -o json 2>/dev/null | grep gitVersion | awk -F'"' '{print $4}') ;;
kubelet) VERSION=$(kubelet --version | awk '{print $2}') ;;
kubeadm) VERSION=$(kubeadm version -o short) ;;
esac
echo "[CHECK] $BINARY $VERSION at $INSTALLED_PATH"
# Download official checksum
CHECKSUM_URL="https://dl.k8s.io/release/${VERSION}/bin/${ARCH}/${BINARY}.sha256"
OFFICIAL_HASH=$(curl -sL "$CHECKSUM_URL")
# Compute installed hash
INSTALLED_HASH=$(sha256sum "$INSTALLED_PATH" | awk '{print $1}')
if [[ "$OFFICIAL_HASH" == "$INSTALLED_HASH" ]]; then
echo "[PASS] $BINARY integrity verified"
else
echo "[FAIL] $BINARY hash mismatch!"
echo " Installed: $INSTALLED_HASH"
echo " Official: $OFFICIAL_HASH"
FAILED=$((FAILED + 1))
fi
done
if [[ $FAILED -gt 0 ]]; then
echo ""
echo "[ALERT] $FAILED binary(ies) failed verification!"
exit 1
else
echo ""
echo "[OK] All binaries verified successfully"
exit 0
fi
Running the Script
chmod +x verify-k8s-binaries.sh
./verify-k8s-binaries.sh
Expected output (all binaries clean):
[CHECK] kubectl v1.29.2 at /usr/local/bin/kubectl
[PASS] kubectl integrity verified
[CHECK] kubelet v1.29.2 at /usr/bin/kubelet
[PASS] kubelet integrity verified
[CHECK] kubeadm v1.29.2 at /usr/bin/kubeadm
[PASS] kubeadm integrity verified
[OK] All binaries verified successfully
What to Do When Verification Fails
| Step | Action |
|---|---|
| 1 | Isolate the node — Cordon and drain: kubectl cordon node01 && kubectl drain node01 --ignore-daemonsets |
| 2 | Preserve evidence — Copy the tampered binary: cp /usr/bin/kubelet /tmp/kubelet-tampered |
| 3 | Replace the binary — Install the verified official version |
| 4 | Investigate — Check systemd logs, audit logs, and file timestamps for who changed the binary |
| 5 | Check other nodes — Verify binaries on all remaining nodes |
| 6 | Rotate credentials — Assume compromise; rotate certificates and ServiceAccount tokens |
Exam Tips
| Tip | Details |
|---|---|
| Know the download URL pattern | https://dl.k8s.io/release/<version>/bin/linux/amd64/<binary> |
| Know the checksum URL | Same URL with .sha256 appended |
| Know the verification command | echo "$(cat binary.sha256) binary" \| sha256sum --check |
| sha256sum vs sha512sum | Both work the same way — --check flag validates |
| Compare installed binary | sha256sum /usr/bin/kubelet vs downloaded checksum |
| Two spaces | The format is hash filename (two spaces between hash and filename) |
Practice Questions
Q1: Download kubectl v1.29.2 for Linux amd64 and verify its integrity using sha256sum. Write every command.
Show Answer
# Step 1: Download the binary
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubectl"
# Step 2: Download the checksum
curl -LO "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubectl.sha256"
# Step 3: Verify
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
# Expected output: kubectl: OK
# Step 4: Install if verification passed
chmod +x kubectl
sudo mv kubectl /usr/local/bin/kubectl
# Step 5: Confirm
kubectl version --client
Important: The format for sha256sum --check requires exactly two spaces between the hash and the filename. The echo "$(cat kubectl.sha256) kubectl" command constructs this format correctly.
Q2: The kubelet binary on node01 may have been tampered with. Write the commands to verify its integrity without disrupting the running cluster.
Show Answer
# SSH to the node (or use kubectl debug node)
ssh node01
# Step 1: Find the kubelet binary and its version
which kubelet
# /usr/bin/kubelet
kubelet --version
# Kubernetes v1.29.2
# Step 2: Compute the hash of the installed binary
sha256sum /usr/bin/kubelet
# e.g., a1b2c3d4... /usr/bin/kubelet
# Step 3: Download the official checksum for that version
curl -sL "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubelet.sha256"
# e.g., a1b2c3d4...
# Step 4: Compare
INSTALLED=$(sha256sum /usr/bin/kubelet | awk '{print $1}')
OFFICIAL=$(curl -sL "https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubelet.sha256")
if [[ "$INSTALLED" == "$OFFICIAL" ]]; then
echo "PASS: kubelet is authentic"
else
echo "FAIL: kubelet has been tampered with!"
fi
Why this doesn’t disrupt the cluster:
- We’re only reading the binary file and computing its hash
- The running kubelet process is not affected
- No services are restarted during verification
Q3: What is the difference between sha256sum and sha512sum? When would you use each?
Show Answer
| Feature | sha256sum | sha512sum |
|---|---|---|
| Hash length | 256 bits (64 hex characters) | 512 bits (128 hex characters) |
| Security | Considered secure for integrity verification | Higher collision resistance |
| Speed | Slightly faster | Slightly slower |
| Usage | Most common for binary verification | Used when stronger guarantees needed |
| Kubernetes | Official checksums use sha256 | Some tooling uses sha512 |
When to use sha256sum:
- Verifying Kubernetes binaries (official checksums are sha256)
- General integrity checking
- When the checksum file ends in
.sha256
When to use sha512sum:
- When the provided checksum is 128 characters (sha512)
- When the checksum file ends in
.sha512 - When organizational policy requires sha512
On the CKS exam: Use whichever the question specifies. The commands work identically — only the hash length differs.
# Both use the same syntax
echo "$(cat file.sha256) file" | sha256sum --check
echo "$(cat file.sha512) file" | sha512sum --check
Q4: An attacker gained access to a node and replaced the kubeadm binary. The hash doesn’t match. What steps should you take to remediate?
Show Answer
Immediate response:
# 1. Cordon the node to prevent new Pods from being scheduled
kubectl cordon node01
# 2. Drain the node to move existing workloads off
kubectl drain node01 --ignore-daemonsets --delete-emptydir-data
# 3. Preserve the tampered binary for forensic analysis
ssh node01 "cp /usr/bin/kubeadm /tmp/kubeadm-tampered-$(date +%Y%m%d)"
# 4. Download and verify the official binary
ssh node01 "
curl -LO https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubeadm
curl -LO https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubeadm.sha256
echo \"\$(cat kubeadm.sha256) kubeadm\" | sha256sum --check
chmod +x kubeadm
sudo mv kubeadm /usr/bin/kubeadm
"
# 5. Verify all other binaries on this node
ssh node01 "
for bin in kubectl kubelet kubeadm; do
echo \"Checking \$bin...\"
sha256sum /usr/bin/\$bin 2>/dev/null || sha256sum /usr/local/bin/\$bin 2>/dev/null
done
"
# 6. Check all other nodes
for node in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do
echo "Checking $node..."
ssh "$node" "sha256sum /usr/bin/kubelet"
done
Follow-up actions:
- Review system audit logs (
/var/log/auth.log,journalctl) for unauthorized access - Rotate all certificates on the node (
kubeadm certs renew all) - Check if any Pods on the node had elevated privileges abused
- Report the incident to the security team
- Consider reimaging the node from a known-clean image
Q5: Why isn’t GPG signature verification used for Kubernetes binaries instead of just checksum comparison?
Show Answer
Current state: Kubernetes releases provide sha256 checksums alongside the binaries. GPG signatures are available for some artifacts but are not the primary verification method.
Why checksums are sufficient for most cases:
- Checksums verify that the binary you downloaded matches what was published
- If you download from
https://dl.k8s.io(HTTPS), TLS protects against in-transit tampering - The combination of HTTPS + checksum verification covers the main threat vectors
What GPG adds:
- Identity verification — GPG proves the binary was signed by a specific key (the Kubernetes release team)
- Protection against server compromise — If
dl.k8s.iois compromised, an attacker can replace both the binary AND the checksum. GPG signatures are harder to forge without the private key. - Non-repudiation — A signature proves the release team published this binary
Limitations of checksum-only verification:
- If the download server is compromised, both the binary and checksum can be replaced
- Checksums don’t prove who created the file — only that it hasn’t been modified since the checksum was computed
- Mirror poisoning attacks can serve matching tampered binary + tampered checksum
On the CKS exam: You only need to demonstrate checksum verification. GPG signature verification is not tested but is worth understanding for production security.
| ← GUI Access Control | Hands-On Lab → |