Code Snippet

Date: 2025-03-22
From: Exploring kubernetes privileged pods
Language: bash
Title: getcapabilitiesofpod.sh
#!/bin/bash

# Define color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[0;37m'
BOLD='\033[1m'
BG_RED='\033[41m'
BG_GREEN='\033[42m'
BG_BLUE='\033[44m'
NC='\033[0m' # No Color

# Function for colorful section headers
print_header() {
  echo -e "\n${BG_BLUE}${BOLD}${WHITE} $1 ${NC}"
  echo -e "${BLUE}$(printf '=%.0s' {1..70})${NC}"
}

# Function for sub-headers
print_subheader() {
  echo -e "\n${BOLD}${CYAN} $1 ${NC}"
  echo -e "${CYAN}$(printf '-%.0s' {1..70})${NC}"
}

# Function to show status
show_status() {
  if [ "$2" == "OK" ]; then
    echo -e "[$1] ${GREEN}✓ $3${NC}"
  elif [ "$2" == "WARN" ]; then
    echo -e "[$1] ${YELLOW}⚠ $3${NC}"
  else
    echo -e "[$1] ${RED}✗ $3${NC}"
  fi
}

# Start minikube if not running
print_header "KUBERNETES SECURITY TEST SUITE"
echo -e "${YELLOW}Initializing test environment...${NC}"

show_status "SETUP" "WARN" "Checking if minikube is running"
if minikube status &> /dev/null; then
  show_status "SETUP" "OK" "Minikube is running"
else
  show_status "SETUP" "WARN" "Starting minikube"
  minikube start
  show_status "SETUP" "OK" "Minikube started successfully"
fi

# Wait for default service account
show_status "SETUP" "WARN" "Waiting for default service account"
while ! kubectl get serviceaccount default &> /dev/null; do
  sleep 2
  echo -n -e "${YELLOW}.${NC}"
done
show_status "SETUP" "OK" "Default service account is available"

# Ensure bc is installed on minikube node
show_status "SETUP" "WARN" "Checking if bc is installed in minikube"
minikube ssh "command -v bc &> /dev/null || { echo 'Installing bc...'; sudo apt-get update && sudo apt-get install -y bc; }"
show_status "SETUP" "OK" "bc is available in minikube"

# Function to check namespaces and capabilities
check_container() {
  POD_NAME=$1
  echo "CHECKING CONTAINER: $POD_NAME"
  
  # Get container ID
  CONTAINER_ID=$(kubectl get pod $POD_NAME -o 'jsonpath={.status.containerStatuses[0].containerID}' | sed 's/docker:\/\///')
  echo -e "${BOLD}Container ID:${NC} ${YELLOW}$CONTAINER_ID${NC}"
  
  # Check namespaces and compare with host
  minikube ssh "
    # Get container PID
    CONTAINER_PID=\$(sudo docker inspect --format='{{.State.Pid}}' $CONTAINER_ID)
    echo -e \"Container PID on host: \${CONTAINER_PID}\"
    echo \"\"
    
    # Compare namespaces
    echo -e \"\033[1;36m--- Namespace Comparison ---\033[0m\"
    echo -e \"\033[1mNAMESPACE  HOST-ID                 CONTAINER-ID             STATUS\033[0m\"
    echo -e \"\033[36m---------- ----------------------- ------------------------ --------\033[0m\"
    for NS in cgroup ipc mnt net pid user uts; do
      HOST_NS=\$(sudo readlink /proc/1/ns/\$NS)
      CONTAINER_NS=\$(sudo readlink /proc/\$CONTAINER_PID/ns/\$NS)
      
      # Extract just the ID number for cleaner display
      HOST_ID=\$(echo \$HOST_NS | sed 's/.*\\[\\(.*\\)\\]/\\1/')
      CONTAINER_ID=\$(echo \$CONTAINER_NS | sed 's/.*\\[\\(.*\\)\\]/\\1/')
      
      SHARED=\$([ \"\$HOST_NS\" = \"\$CONTAINER_NS\" ] && echo -e \"\033[31mSHARED\033[0m\" || echo -e \"\033[32mISOLATED\033[0m\")
      printf \"%-10s %-25s %-24s %b\\n\" \"\$NS\" \"\$HOST_ID\" \"\$CONTAINER_ID\" \"\$SHARED\"
    done
    
    echo \"\"
    echo -e \"\033[1;36m--- Capability Information ---\033[0m\"
    echo \"Checking capabilities from /proc/\$CONTAINER_PID/status:\"
    echo \"\"
    echo -e \"\033[1;33m### Container Capabilities ###\033[0m\"
    CONT_CAP_EFF=\$(sudo grep CapEff /proc/\$CONTAINER_PID/status | awk '{print \$2}')
    CONT_CAP_PRM=\$(sudo grep CapPrm /proc/\$CONTAINER_PID/status | awk '{print \$2}')
    CONT_CAP_INH=\$(sudo grep CapInh /proc/\$CONTAINER_PID/status | awk '{print \$2}')
    CONT_CAP_BND=\$(sudo grep CapBnd /proc/\$CONTAINER_PID/status | awk '{print \$2}')
    CONT_CAP_AMB=\$(sudo grep CapAmb /proc/\$CONTAINER_PID/status | awk '{print \$2}')
    
    echo -e \"\033[1mCapEff (Effective):  \033[0m \033[33m\$CONT_CAP_EFF\033[0m\"
    echo -e \"\033[1mCapPrm (Permitted):  \033[0m \033[33m\$CONT_CAP_PRM\033[0m\"
    echo -e \"\033[1mCapInh (Inheritable):\033[0m \033[33m\$CONT_CAP_INH\033[0m\"
    echo -e \"\033[1mCapBnd (Bounding):   \033[0m \033[33m\$CONT_CAP_BND\033[0m\"
    echo -e \"\033[1mCapAmb (Ambient):    \033[0m \033[33m\$CONT_CAP_AMB\033[0m\"
    
    # Save effective capabilities for summary comparison
    echo \$CONT_CAP_EFF > /tmp/${POD_NAME}_capeff
    
    # Decode effective capabilities 
    echo \"\"
    echo -e \"\033[1;33m### Decoded Effective Capabilities ###\033[0m\"
    echo \"The effective capabilities (CapEff) determine what privileged operations a process can actually perform.\"
    echo \"\"
    
    # Using bc to decode capabilities
    echo \"Using bc to decode capabilities...\"
    
    # Using a simplified list of common capabilities for demonstration
    cap_map=(
      \"0:CAP_CHOWN - Change file ownership and group\"
      \"1:CAP_DAC_OVERRIDE - Bypass file read, write, and execute permission checks\"
      \"2:CAP_DAC_READ_SEARCH - Bypass file read permission checks\"
      \"3:CAP_FOWNER - Bypass permission checks on operations that normally require the file system UID to match the process's\"
      \"4:CAP_FSETID - Don't clear set-user-ID and set-group-ID mode bits when a file is modified\"
      \"5:CAP_KILL - Bypass permission checks for sending signals\"
      \"6:CAP_SETGID - Make arbitrary manipulations of process GIDs\"
      \"7:CAP_SETUID - Make arbitrary manipulations of process UIDs\"
      \"8:CAP_SETPCAP - Modify process capabilities\"
      \"9:CAP_LINUX_IMMUTABLE - Set the FS_APPEND_FL and FS_IMMUTABLE_FL flags\"
      \"10:CAP_NET_BIND_SERVICE - Bind a socket to Internet domain privileged ports\"
      \"11:CAP_NET_BROADCAST - Make socket broadcasts and listen to multicasts\"
      \"12:CAP_NET_ADMIN - Perform network administration tasks\"
      \"13:CAP_NET_RAW - Use raw sockets\"
      \"14:CAP_IPC_LOCK - Lock memory\"
      \"15:CAP_IPC_OWNER - Bypass permissions on message queues and shared memory\"
      \"16:CAP_SYS_MODULE - Load and unload kernel modules\"
      \"17:CAP_SYS_RAWIO - Perform I/O port operations\"
      \"18:CAP_SYS_CHROOT - Use chroot()\"
      \"19:CAP_SYS_PTRACE - Trace arbitrary processes\"
      \"20:CAP_SYS_PACCT - Configure process accounting\"
      \"21:CAP_SYS_ADMIN - Perform various system administration operations\"
      \"22:CAP_SYS_BOOT - Use reboot() and kexec_load()\"
      \"23:CAP_SYS_NICE - Raise process nice value and change nice value for arbitrary processes\"
      \"24:CAP_SYS_RESOURCE - Override resource limits\"
      \"25:CAP_SYS_TIME - Set system clock\"
      \"26:CAP_SYS_TTY_CONFIG - Configure TTY devices\"
      \"27:CAP_MKNOD - Create special files\"
      \"28:CAP_LEASE - Establish leases on files\"
      \"29:CAP_AUDIT_WRITE - Write records to kernel auditing log\"
      \"30:CAP_AUDIT_CONTROL - Configure audit subsystem\"
      \"31:CAP_SETFCAP - Set file capabilities\"
      \"32:CAP_MAC_OVERRIDE - Override MAC restrictions\"
      \"33:CAP_MAC_ADMIN - Configure MAC\"
      \"34:CAP_SYSLOG - Perform privileged syslog operations\"
      \"35:CAP_WAKE_ALARM - Trigger wake alarms\"
      \"36:CAP_BLOCK_SUSPEND - Block system suspend\"
      \"37:CAP_AUDIT_READ - Read audit log\"
    )
    
    # Convert hex to binary
    binary=\$(printf \"%064s\" \$(bc <<< \"obase=2;ibase=16;\${CONT_CAP_EFF^^}\") | tr ' ' '0')
    
    # Reverse for bit position
    reversed_binary=\$(echo \$binary | rev)
    
    echo -e \"Capability hex: \033[36m\$CONT_CAP_EFF\033[0m\"
    
    # Check each bit and display capability if set
    for cap in \"\${cap_map[@]}\"; do
      pos=\$(echo \$cap | cut -d':' -f1)
      desc=\$(echo \$cap | cut -d':' -f2-)
      
      if [ \"\${reversed_binary:\$pos:1}\" = \"1\" ]; then
        echo -e \" - \033[32m\$desc\033[0m\"
      fi
    done
  "
  echo ""
}

print_header "KUBERNETES NAMESPACE & CAPABILITY TESTS"

# 1. Create a baseline pod (no special privileges)
echo "CREATING POD 1: baseline-pod (no special privileges)"
POD_MANIFEST=$(cat </dev/null)" != "Running" ]; do
    sleep 2
    echo -n -e "${YELLOW}.${NC}"
  done
  echo -e " ${GREEN}Running!${NC}"
done
echo -e "${GREEN}All pods are running${NC}"
echo ""

# Check capabilities for all pods
for pod in "${PODS[@]}"; do
  check_container "$pod"
done

# Generate a capabilities comparison summary
print_header "CAPABILITIES COMPARISON SUMMARY"
echo "This table shows which critical capabilities are granted to each pod configuration."
echo ""

# Use minikube to generate the comparison
minikube ssh "
  # Define key capabilities to check for
  declare -a CAPS=(
    '21:SYS_ADMIN'
    '12:NET_ADMIN'
    '19:SYS_PTRACE'
    '16:SYS_MODULE'
    '7:SETUID'
    '24:SYS_RESOURCE'
    '17:SYS_RAWIO'
  )
  
  # Print table header with colors
  printf \"\033[1;36m%-20s\" \"POD NAME\"
  for cap in \"\${CAPS[@]}\"; do
    capname=\$(echo \$cap | cut -d':' -f2)
    printf \"\033[1;36m%-12s\" \"\$capname\"
  done
  printf \"\033[0m\\n\"
  
  # Print separator
  printf \"\033[36m%s\" \"--------------------\"
  for cap in \"\${CAPS[@]}\"; do
    printf \"%s\" \"------------\"
  done
  printf \"\033[0m\\n\"
  
  # Check each pod
  for pod in baseline-pod privileged-pod hostnetwork-pod hostpid-pod hostipc-pod; do
    if [ -f \"/tmp/\${pod}_capeff\" ]; then
      capeff=\$(cat /tmp/\${pod}_capeff)
      
      # Convert hex to binary
      binary=\$(printf \"%064s\" \$(bc <<< \"obase=2;ibase=16;\${capeff^^}\") | tr ' ' '0')
      
      # Reverse for bit position
      reversed_binary=\$(echo \$binary | rev)
      
      # Print pod name
      printf \"\033[1;33m%-20s\033[0m\" \"\$pod\"
      
      # Check each capability
      for cap in \"\${CAPS[@]}\"; do
        pos=\$(echo \$cap | cut -d':' -f1)
        
        if [ \"\${reversed_binary:\$pos:1}\" = \"1\" ]; then
          printf \"\033[1;32m%-12s\033[0m\" \"YES\"
        else
          printf \"\033[1;31m%-12s\033[0m\" \"NO\"
        fi
      done
      printf \"\\n\"
    else
      printf \"\033[1;33m%-20s \033[1;31mCAPABILITY DATA NOT FOUND\033[0m\\n\" \"\$pod\"
    fi
  done
"

# Cleanup
print_header "CLEANUP"
echo -e "${YELLOW}Cleaning up resources...${NC}"
for pod in "${PODS[@]}"; do
  kubectl delete pod $pod --force --wait=false 2>/dev/null
  show_status "CLEANUP" "OK" "Deleted pod: $pod"
done
minikube ssh "sudo rm -f /tmp/*_capeff"
echo -e "${GREEN}${BOLD}All done! Tests completed successfully!${NC}"
| View Source