Repository navigation
script_matches: don't report a match when the interpreter differs - #567
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With intercept_verify, ptrace_verify_post_exec() compares the program that actually started against the command the policy approved. When the approved command is a #! script, execve_args_match() calls script_matches() to accept the script's interpreter instead. But if the interpreter does not match the real executable and the nested-interpreter case doesn't apply, script_matches() falls through to the success path and returns 1, so execve_args_match() skips argv[0] and compares only the rest of argv and the environment. A traced process that swaps the execve path after the policy check (the race intercept_verify is meant to catch) can therefore run any binary as the runas user with argv
x /path/to/approved.sh args...and verification still passes. The "can't open" / "not a script" / interpreter argument failures on a nested level returned a non-zero skip the same way.Treat an interpreter mismatch as a failure and only return a skip count once the whole #! chain has matched. I checked this on Linux by calling execve_args_match() from the real exec_ptrace.c (the test_ptrace.c include trick): with
/tmp/allowed.sh(#!/bin/sh) approved,/usr/bin/idwith argvx /tmp/allowed.sh argwas accepted before and is rejected now. The same holds for#!/bin/sh -eand for a nested#!/tmp/inner.shscript, while the legitimate/bin/sh /tmp/allowed.sh arg,/bin/sh -e ...and/bin/sh inner.sh outer.sh argforms still match.