RC RANDOM CHAOS

GTFOBins catalogues privilege misconfiguration

GTFOBins documents a structural property of Unix privilege: grants bind to binaries, not operations, and the gap is the escalation surface.

· 9 min read

Opening Claim

GTFOBins is not an attack tool. It is a documentation project that catalogues Unix binaries which, when present in privileged execution contexts, can be used to break out of those contexts. The site organises binaries by capability: shell spawning, file read, file write, SUID escalation, sudo escalation, capability abuse, library loading. Every binary on that list, present in a privileged context where it does not strictly need to be, is a control failure already in place. The catalogue does not create the failure. It documents it.

The position from a defender’s view is direct. GTFOBins is a public inventory of how trusted binaries become attack primitives. The binaries themselves are not malicious. They are standard system utilities. Their abuse depends entirely on the privilege the operating system grants them and the assumptions an operator made when granting it. The project’s existence does not introduce risk into an environment. It exposes risk that already exists in how privilege has been assigned.

The pattern matters more than the catalogue. A binary like find, awk, vi, or less is not, in isolation, an attacker capability. A binary like find with the SUID bit set, or permitted in a sudoers entry without argument restriction, is. The control boundary is not the binary. It is the privilege configuration around it. GTFOBins documents the consequences of misjudging that boundary, and it does so in a format that is equally useful to a penetration tester running an engagement and a defender reviewing a host hardening baseline. Both parties read it for the same reason: to know which binaries cannot be granted privilege casually.

What Actually Failed

The failure is not in the binary. It is in the trust relationship between the binary and the privilege granted to it. When an administrator marks a binary SUID root, or adds it to a sudoers NOPASSWD entry, the operating system enforces the privilege grant exactly as written. The kernel does not evaluate whether the named binary is capable of spawning an interactive shell, reading arbitrary files, executing arbitrary subcommands, or loading attacker-controlled libraries under the granted privilege. The kernel grants what the configuration declares. Nothing more, nothing less.

The observable behaviour on a compromised host is consistent. A user invokes a permitted binary. The binary executes under elevated privilege. Within that execution the binary exposes a documented feature: a shell escape sequence, a command flag that invokes subprocesses, a file write primitive, a script-evaluation argument. The binary performs the action it was designed to perform. The privilege travels with the execution. The user reaches a root shell, reads a protected file, or writes to a controlled path. All of this occurs within the bounds of what the operating system was told to permit.

No control was bypassed in this path. The control was authored to permit the action. The administrator’s mental model was that the user would only invoke the binary for its intended administrative purpose. That mental model is not enforced by the system. The system enforces the configuration string. The gap between administrator intent and configuration semantics is the operating space GTFOBins documents. The catalogue does not describe vulnerabilities. It describes intended binary features executing under privilege the operator did not realise covered them.

Why It Failed

The pattern persists because Unix privilege grants are coarse by design. A sudoers entry permitting /usr/bin/find for a user does not constrain which arguments find may take, which files it may operate on, or which subprocesses it may spawn through -exec. The privilege is bound to the binary identifier, not to the operation. Once the binary executes with elevated privilege, every feature that binary exposes is available under that privilege. The same property holds for SUID bits, file capabilities, container runtime mounts, and any other mechanism that binds privilege to a binary path rather than to a parameterised action.

Configuration review processes typically validate that a binary is required for an administrative task. They rarely validate the full feature surface of that binary against the privilege being granted. An administrator confirms that find is needed for a scheduled cleanup task and approves the sudoers entry. The administrator does not enumerate find’s -exec, -fprintf, and -newerXY flags and assess that they collectively permit arbitrary command execution and arbitrary file write under the granted privilege. The binary’s documented behaviour is not modelled as part of the threat surface during the privilege grant decision. GTFOBins exists, in part, because that modelling step is consistently skipped.

Detection on this path is also weak in default configurations. The binary is on the allow list. Its execution is expected. Its child processes inherit the elevated context. A shell spawned by find under sudo, from the perspective of standard process auditing, is a permitted invocation of find followed by a permitted child process under the same user context. Without explicit instrumentation of binary-feature abuse patterns, parent-child relationships across privilege boundaries, and argument-level inspection of permitted invocations, the activity is indistinguishable from legitimate use. The control failure is not a policy violation. It is a configuration operating exactly as it was written, against a feature surface the author did not enumerate.

Mechanism of Failure or Drift

The mechanism is a binding mismatch. Unix privilege grants are bound to a binary identifier or a binary path. The operations a defender actually wants to permit are bound to a narrower intent: cleanup of /var/log, restart of a specific service, read of a specific configuration file. The configuration syntax does not express that intent. It expresses the binary. Every feature the binary supports is in scope of the grant, whether or not the operator considered those features when authoring the rule. The kernel and the sudo policy engine enforce the configuration as written. They do not enforce the operator’s mental model of what the binary is for.

Drift compounds the failure. A sudoers entry authored to permit a single administrative action persists across operating system upgrades, package updates, and personnel turnover. The binary it references gains features over time. New flags are added. New subcommand syntaxes appear. Behaviours that were not exposed at the time of the original grant become exposed later under the same configuration line. The grant does not version with the binary. The binary’s feature surface expands while the privilege boundary stays the same. GTFOBins entries are frequently updated to reflect newly recognised escape paths in binaries that have been on systems for decades. The configurations granting privilege to those binaries are rarely revisited with the same cadence.

The second drift vector is inheritance. Configurations are copied between hosts, between images, between roles. A sudoers fragment authored on a build host for a specific automation task is templated into a base image. The base image is consumed by hosts that do not run that automation but inherit the grant. Container images carry SUID binaries from upstream layers that downstream consumers never audited. The privilege grant survives the loss of context. The original justification for the grant is no longer present in the environment, but the grant remains, and the binary it points to still exposes the same feature surface to whichever user the inherited rule names.

Expansion into Parallel Pattern

The same binding mismatch appears in cloud identity systems. An IAM policy that grants iam:PassRole on a wildcard resource, or sts:AssumeRole into a broadly trusted role, binds privilege to an action verb without constraining the operation that verb enables. A principal permitted to pass any role into any compute service can elevate to whichever role has the highest privilege in the account. The policy author intended to permit one workflow. The policy as written permits the full feature surface of the action. The cloud control plane enforces the policy string, not the intent. The catalogue equivalent of GTFOBins for this domain is the set of known privilege escalation paths through service-linked roles, role chaining, and resource-policy trust relationships. The mechanism is identical: privilege bound to an identifier, feature surface broader than the author modelled.

Container runtimes reproduce the pattern. A container granted the Docker socket, the host PID namespace, or CAP_SYS_ADMIN is granted the full feature surface those primitives expose. The grant is authored to enable a specific function: a monitoring agent, a build runner, a debugging sidecar. The runtime enforces the grant as a capability, not as a function. Any process inside the container can use the capability for any purpose the kernel permits under it. The Docker socket is, at the trust-boundary level, equivalent to a SUID root binary. It is a primitive that converts in-container execution into host-level execution. The configuration that mounts it does not constrain which container processes may use it or for what.

Windows systems exhibit the same class through signed binaries that ship with the operating system. Binaries cataloged under LOLBAS execute under user privilege but expose features such as arbitrary download, arbitrary execution, and AppLocker bypass that defenders did not model when authorising the binary’s presence. The binary is signed by Microsoft. It is on the allow list because removing it would break the operating system. Its features are documented. The control failure is the same: privilege and trust bound to the binary identifier rather than to the operation, with a feature surface broader than the policy author enumerated. CI/CD systems show it again, where a build agent’s service account holds permissions scoped to a job identifier rather than to the operations the job is supposed to perform, and any code the job executes inherits the full grant.

Hard Closing Truth

GTFOBins is not the problem and removing it would not reduce risk. The catalogue documents a structural property of how privilege is expressed in Unix-derived systems. The property is that grants are coarse, feature surfaces are wide, and the gap between the two is the operating space for privilege escalation. The same property exists in cloud IAM, container runtimes, Windows signed binaries, and CI/CD permission models. The catalogue makes the property legible. Legibility is not the failure. The failure is the configuration that depends on the property being illegible.

A control that grants a binary is not a control over the operation the operator intended to permit. It is a control over every operation the binary can perform. If the binary can spawn a shell, the grant includes shell spawning. If the binary can read arbitrary files, the grant includes arbitrary file read. If the binary can write, evaluate scripts, load libraries, or invoke subprocesses, the grant includes all of those. Treating the grant as anything narrower is a misreading of what the system is enforcing. Controls that are not enforced are not controls. Privilege grants whose feature surface has not been enumerated are not controls either. They are configurations whose effects have not been measured.

The operator position is that any privilege grant to a named binary, role, capability, or signed executable must be evaluated against the full feature surface of the thing being granted, not against the intended use. Grants must be bound to operations where the underlying system supports it: sudoers with explicit argument constraints, IAM policies with resource and condition scoping, container security profiles that drop capabilities to the minimum required, AppLocker and WDAC policies that constrain signed-binary execution paths. Where the system does not support binding to operations, the grant is a privileged execution context and must be treated as one, with the auditing, monitoring, and lifecycle review that implies. Anything else is a configuration that documents the gap GTFOBins exists to publish.

Share

Keep Reading

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.