Saltar al contenido principal

Security Context

El securityContext define los privilegios y controles de acceso para pods y contenedores. Una mala configuración puede permitir la escalada de privilegios, escape del contenedor o compromiso del nodo.

Pods privilegiados

Un contenedor privilegiado tiene acceso casi completo al nodo host.

jq -r '
.items[]
| select(
(.spec.containers[]?.securityContext.privileged == true)
or (.spec.initContainers[]?.securityContext.privileged == true)
)
| [.metadata.namespace, .metadata.name] | @tsv' pods.json

Ejecución como root

jq -r '
.items[]
| select(
(.spec.containers[]?.securityContext.runAsUser == 0)
or (.spec.containers[]?.securityContext.runAsNonRoot == false)
or (.spec.securityContext?.runAsUser == 0)
)
| [.metadata.namespace, .metadata.name] | @tsv' pods.json

Sin restricción de usuario (sin runAsNonRoot ni runAsUser)

Pods donde no se especifica ningún control de usuario — corren como root por defecto si la imagen no lo cambia.

jq -r '
.items[]
| select(
(.spec.securityContext?.runAsNonRoot == null)
and (.spec.securityContext?.runAsUser == null)
and (
.spec.containers[]?
| (.securityContext?.runAsNonRoot == null)
and (.securityContext?.runAsUser == null)
)
)
| [.metadata.namespace, .metadata.name] | @tsv' pods.json

Escalada de privilegios permitida

jq -r '
.items[]
| select(
(.spec.containers[]?.securityContext.allowPrivilegeEscalation == true)
or (.spec.initContainers[]?.securityContext.allowPrivilegeEscalation == true)
)
| [.metadata.namespace, .metadata.name] | @tsv' pods.json

Sin perfil Seccomp

Pods que no tienen perfil seccomp definido a nivel de pod ni de contenedor.

jq -r '
.items[]
| select(
(.spec.securityContext?.seccompProfile == null)
and (.spec.containers[]?.securityContext?.seccompProfile == null)
)
| [.metadata.namespace, .metadata.name] | @tsv' pods.json

Pods con capabilities añadidas

jq -r '
.items[]
| . as $pod
| .spec.containers[]?
| select(.securityContext.capabilities.add? | length > 0)
| [$pod.metadata.namespace, $pod.metadata.name, .name,
(.securityContext.capabilities.add | join(","))]
| @tsv' pods.json

Capabilities especialmente peligrosas

CapabilityRiesgo
SYS_ADMINEquivale casi a root; permite montaje, namespaces, etc.
NET_ADMINControl total de red del nodo
SYS_PTRACEPuede inyectar código en procesos del host
DAC_OVERRIDEOmite comprobaciones de permisos de archivos
CAP_SETUID / CAP_SETGIDCambio arbitrario de UID/GID
DANGEROUS="SYS_ADMIN|NET_ADMIN|SYS_PTRACE|DAC_OVERRIDE|SETUID|SETGID|SYS_MODULE"

jq -r --arg caps "$DANGEROUS" '
.items[]
| . as $pod
| .spec.containers[]?
| select(
.securityContext.capabilities.add?
| map(test($caps)) | any
)
| [$pod.metadata.namespace, $pod.metadata.name, .name,
(.securityContext.capabilities.add | join(","))]
| @tsv' pods.json

Acceso a namespaces del host

jq -r '
.items[]
| select(
(.spec.hostPID == true)
or (.spec.hostIPC == true)
or (.spec.hostNetwork == true)
)
| [.metadata.namespace, .metadata.name,
"hostPID=\(.spec.hostPID // false)",
"hostIPC=\(.spec.hostIPC // false)",
"hostNetwork=\(.spec.hostNetwork // false)"]
| @tsv' pods.json

Sistema de archivos raíz sin modo de solo lectura

jq -r '
.items[]
| . as $pod
| .spec.containers[]?
| select((.securityContext?.readOnlyRootFilesystem // false) == false)
| [$pod.metadata.namespace, $pod.metadata.name, .name] | @tsv' pods.json

Volúmenes hostPath montados

Un hostPath puede exponer rutas sensibles del nodo (e.g., /, /etc, /var/run/docker.sock).

jq -r '
.items[]
| . as $pod
| .spec.volumes[]?
| select(.hostPath != null)
| [$pod.metadata.namespace, $pod.metadata.name, .name, .hostPath.path]
| @tsv' pods.json

Resumen de configuración insegura por pod

Muestra todos los problemas de seguridad encontrados en cada pod en una sola pasada.

jq -r '
.items[]
| . as $pod
| [
if .spec.hostPID then "hostPID" else empty end,
if .spec.hostIPC then "hostIPC" else empty end,
if .spec.hostNetwork then "hostNetwork" else empty end,
if (.spec.volumes[]? | .hostPath) then "hostPath" else empty end,
if (.spec.containers[]?.securityContext.privileged == true) then "privileged" else empty end,
if (.spec.containers[]?.securityContext.allowPrivilegeEscalation == true) then "allowPrivEsc" else empty end,
if (.spec.securityContext?.runAsUser == 0 or .spec.containers[]?.securityContext.runAsUser == 0) then "runAsRoot" else empty end
] as $flags
| select($flags | length > 0)
| [$pod.metadata.namespace, $pod.metadata.name, ($flags | join(","))]
| @tsv' pods.json