PT-2026-113977 · Red Hat · Red Hat Openshift Container Platform 4
CVE-2026-104795
·
Publicado
2026-10-14
·
Atualizado
2026-10-14
CVSS v3.1
8.8
Alta
| Vetor | AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H |
The insights-runtime-extractor runs as a privileged DaemonSet (
hostPID: true)
that scans container processes for runtime fingerprinting. When scanning a
container, the coordinator:- fork()s a child process
- setns() into the target container's PID and mount namespaces
- fchdir() back to an orphaned FD pointing at the extractor's own root
filesystem (where
/crio.sockis hostPath-mounted) - Calls only
seteuid(target uid)— changing the effective UID but leaving the real UID and saved-set-UID at 0 and retaining the permitted capability set - The
check no privileged perms()guard inspects only the Effective capability set (so it passes), and is skipped entirely when the target runs as uid 0 - The
VersionExecutablefingerprint invokesfpr kind executablewithprocess.command line[0]— the target's argv[0], read from/proc/<pid>/cmdlineand fully controlled by the workload fpr kind executablecallsexec.Command(executable, "--version").Output()— executing the workload's own binary inside the workload's mount namespace while ruid=0 in the host user namespace
The executed process can call
setuid(0) to restore full root with
CAP SYS ADMIN, and inherits the orphaned cwd which resolves into the extractor
container's filesystem containing the host CRI-O socket.Affected Code
1. Insufficient privilege drop (Rust — extractor coordinator)
File:
extractor/src/insights runtime extractor.rsrust
// Lines 139-146 — seteuid-only drop, guard skipped for root containers
join process namespaces(process.pid)?;
change dir(current dir);
switch user(*process.uid)?;
if *process.uid != 0 {
perms::check no privileged perms()
.expect("Must not have privileged permissions to run fingerprints");
}
fingerprint::run fingerprints(&config, out dir, &process);rust
// Lines 182-185 — only effective UID changed; ruid/suid stay 0
fn switch user(uid: u32) -> Result<(), ScannerError> {
debug!("... Becoming user: {uid}");
seteuid(uid.into()).map err(|e| ScannerError::Errno(e))
}2. Execution of untrusted binary (Go — fingerprint)
File:
fingerprints/pkg/utils/file.gogo
// Lines 75-80 — executes a path taken verbatim from workload's argv[0]
func GetExecutableVersionOutput(executable string) (string, error) {
out, err := exec.Command(executable, "--version").Output()
if err != nil {
return "", err
}
return string(out), nil
}3. Workload-controlled path forwarded (Rust — version executable)
File:
version executable.rsrust
// Lines 29-34 — workload-controlled command line[0] forwarded to fingerprint
return Some(vec![
fpr kind executable,
out dir.to string(),
String::from(&process.command line[0]),
String::from(&version executable.runtime kind name),
]);Attack Pattern
Attacker: Any tenant able to schedule a pod (unprivileged, any namespace)
Victim: The node running the insights-runtime-extractor DaemonSet
Trigger: Automatic — the DaemonSet scans all container processes on the node
Attack sequence:
- Attacker creates a pod whose process name matches a configured
versioned-executable pattern (
node,python,python3,MainThread, or containsjava) - The pod's main binary (at the path matching argv[0]) is a malicious
executable that calls
setuid(0)to restore root - When the insights operator triggers a scan, the DaemonSet forks, enters the attacker's mount namespace, and executes the attacker's binary with ruid=0
- The attacker's code regains full root with
CAP SYS ADMINin the host user namespace - The inherited cwd contains the host CRI-O socket → full node compromise
Correção
Encontrou algum problema na descrição? Tem algo a acrescentar? Fique à vontade para nos escrever 👾
Enumeração de Fraquezas
Identificadores relacionados
Produtos afetados
Red Hat Openshift Container Platform 4