How insecure named pipe security descriptors on Windows worker nodes in pkg/kubelet/winstats allowed container processes to impersonate NT AUTHORITY\SYSTEM.
Imagine a hospital where patients are confined to their recovery rooms, communicating with doctors through an intercom tube. If the hospital installed cheap intercom tubes that don't verify who is speaking, a patient can whisper into the tube claiming to be the chief surgeon, ordering the pharmacy to unlock all drug cabinets.
An attacker gains execution inside a container pod scheduled on a Windows node.
The container connects to the kubelet's unauthenticated named pipe (\\.\pipe\k8s-winstats).
The container induces the kubelet service to call ImpersonateNamedPipeClient().
Because the kubelet runs as SYSTEM, the attacker breaks out to full host administrator.
In lesbarem High-Level-Quellcode bereitgestellt (kein rohes Assembler oder Binär-Diff).
// VULNERABLE: pkg/kubelet/winstats/winstats.go before patch
func createStatsPipe() (net.Listener, error) {
// ROOT CAUSE:
// Empty security descriptor grants World Read/Write permissions to all containers!
// Allows unprivileged container processes to connect and manipulate impersonation tokens!
return winio.ListenPipe(`\\.\pipe\k8s-winstats`, &winio.PipeConfig{
SecurityDescriptor: "", // Insecure default permissions!
})
}
// SECURE: pkg/kubelet/winstats/winstats.go patch
func createStatsPipe() (net.Listener, error) {
// 1. Enforce strict SDDL restricting access exclusively to Local System and Admins
// "D:(A;;GA;;;SY)(A;;GA;;;BA)" -> Discretionary ACL: Grant All to SYSTEM and Built-in Admins
sddl := "D:(A;;GA;;;SY)(A;;GA;;;BA)"
return winio.ListenPipe(`\\.\pipe\k8s-winstats`, &winio.PipeConfig{
SecurityDescriptor: sddl, // Strictly blocks container processes!
})
}