SSH Authorized Keys ForcedCommand and Wrapper Audit
Once you have access, check whether SSH access control is being altered via authorized_keys options or server-side forced commands. This is not about adding persistence. It is about detecting it, documenting it, and understanding why SSH behavior differs per user.
SSH keys are not just authentication tokens. The authorized_keys format supports per-key options that restrict what a key can do after it authenticates. A command= option forces the session to run a single command regardless of what the client requests. A from= option limits which source IPs can use the key. no-pty blocks terminal allocation, no-port-forwarding kills tunneling, and environment= injects variables into the session. These restrictions matter for post-exploitation: they tell you whether a compromised key gives you a full shell or just a constrained channel.
Check per-user authorized_keys options
The risk pattern is authorized_keys entries with restrictive or unexpected options, especially command=. Those options change what happens when a key authenticates. A deployment key with no-pty but no command= still allows non-interactive exec. A key with command="/usr/local/bin/backup.sh" gives you that script and nothing else, unless you can exploit the script itself.
On a host where you have filesystem access:
If you can enumerate other users after privilege gain, check all authorized_keys files on the system. Service accounts and CI/CD identities often carry keys with command= restrictions or tight from= allowlists. An unexpected environment= line can leak credential paths or application secrets.
If you find command=, capture the full line in notes. That is the control point. Note the exact command path, any arguments, and whether SSH_ORIGINAL_COMMAND is referenced inside the script. Scripts that pass SSH_ORIGINAL_COMMAND to a shell are often exploitable for command injection.
Per-key options to audit in authorized_keys:
command=forces a single command on authenticationfrom=restricts which source IPs can use the keyno-ptyblocks terminal allocationno-port-forwardingdisables SSH tunnelingenvironment=injects variables into the session
Check sshd server-side forced command policy
Server-wide forced commands override interactive shells and can make SSH sessions behave inconsistently across users. A ForceCommand directive in sshd_config applies globally unless scoped to a Match block. This is more restrictive than per-key options because it cannot be bypassed by modifying authorized_keys. AuthorizedKeysCommand means the server fetches authorized keys dynamically from a script or external source instead of the filesystem, which is common in LDAP-integrated or cloud SSH setups.
Also check the raw config and any Match blocks. Match blocks apply directives to specific users, groups, or source addresses. A Match User deploy ForceCommand /usr/bin/git-shell entry means the deploy account is jailed to git operations. If you have code execution as that user, you are working inside git-shell, not a standard shell. Match blocks that combine ForceCommand with AllowTcpForwarding no and PermitTTY no are the standard pattern for locked-down deployment identities.
References
-
sshd_config(5) manual pageLINK: sshd_config(5) manual page, man.openbsd.org/sshd_config (opens in new tab)
ForceCommand, Match blocks, AuthorizedKeysCommand, and forwarding controls.
-
ssh(1) manual pageLINK: ssh(1) manual page, man.openbsd.org/ssh (opens in new tab)
Client behavior when forced commands and restricted sessions are in play.