-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Add Rootkit Privilege Escalation Signal Hunter #20643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| register_options([ | ||
| OptInt.new('MIN_SIGNAL', [true, 'Start at signal', 0]), | ||
| OptInt.new('MAX_SIGNAL', [true, 'Stop at signal', 64]), | ||
| OptString.new('PID', [true, 'Process ID to send signals to', '$$']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not work on fish shell as it does not support $$. Regardless, using the current process is by far the safest default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to be extra-fancy and support non-POSIX shells, cut -d ' ' -f 4 /proc/self/stat gets the current PID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to be extra-fancy and support non-POSIX shells,
cut -d ' ' -f 4 /proc/self/statgets the current PID.
This still runs into the same issue with Fish which does not support $() or backticks for command substitution.
$$ is widely supported.
I'm not concerned about supporting Fish. The module that this module replaces also did not support Fish.
| # Iterate from MIN to MAX sending each signal to PID. | ||
| # SIGCONT if the process hangs. | ||
| res = cmd_exec( | ||
| %{i=#{datastore['MIN_SIGNAL']}; while [ "$i" -le #{datastore['MAX_SIGNAL']} ]; do sh -c "kill -$i #{pid}; id" 2>/dev/null & pid=$!; sleep 0.1; kill -CONT "$pid" 2>/dev/null; wait "$pid"; i=$((i + 1)); done 2>/dev/null}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This abomination is designed to be portable, fast, and safe.
- Fast: Faster than calling
cmd_exec(kill ...)for each signal (but not as fast as using a PID which the user doesn't have permission to kill, such as PID 1, or PID for a non-existent process). - Portable: This should work on all POSIX compliant shells, but will fail on
fishdue to lack of support for$!(and$$). - Safe: A new shell is spawned for each attempt, and signals are sent to this PID by default.
Using a different PID (such as PID 1) by default would have made the code much faster and cleaner, but it is not a safe default. The module includes a root check to prevent running as root, but indiscriminately spamming signals at PID 1 is never safe. For example, CAP_KILL allows non-root users to kill arbitrary processes.
An alternative is to use PID 666 by default. This is the default PID used by KoviD rookit. But again, this runs the risk of terminating any legitimate process which happens to use this PID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe putting it on several lines with a join would make it a bit less abominable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Still an abomination.
If we didn't care about leaving a few hung shell processes, the code would be much cleaner (a single command).
| 'Notes' => { | ||
| 'Reliability' => [ REPEATABLE_SESSION ], | ||
| 'Stability' => [ CRASH_OS_DOWN ], | ||
| 'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why SCREEN_EFFECTS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the session is associated with a user with a GUI session, the user may see crash handler popups.
| register_options([ | ||
| OptInt.new('MIN_SIGNAL', [true, 'Start at signal', 0]), | ||
| OptInt.new('MAX_SIGNAL', [true, 'Stop at signal', 64]), | ||
| OptString.new('PID', [true, 'Process ID to send signals to', '$$']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| OptString.new('PID', [true, 'Process ID to send signals to', '$$']) | |
| OptString.new('PID', [true, 'Process ID to send signals to ($$ for the current process)', '$$']) |
Not everyone is fluent in sh-fu, and some people might be unaware of the $$ trick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is the process ID of a newly spawned process, rather than the current process. I've changed the description.
| register_options([ | ||
| OptInt.new('MIN_SIGNAL', [true, 'Start at signal', 0]), | ||
| OptInt.new('MAX_SIGNAL', [true, 'Stop at signal', 64]), | ||
| OptString.new('PID', [true, 'Process ID to send signals to', '$$']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to be extra-fancy and support non-POSIX shells, cut -d ' ' -f 4 /proc/self/stat gets the current PID.
| # Iterate from MIN to MAX sending each signal to PID. | ||
| # SIGCONT if the process hangs. | ||
| res = cmd_exec( | ||
| %{i=#{datastore['MIN_SIGNAL']}; while [ "$i" -le #{datastore['MAX_SIGNAL']} ]; do sh -c "kill -$i #{pid}; id" 2>/dev/null & pid=$!; sleep 0.1; kill -CONT "$pid" 2>/dev/null; wait "$pid"; i=$((i + 1)); done 2>/dev/null}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe putting it on several lines with a join would make it a bit less abominable?
5fa9347 to
0fbf02b
Compare
This module replaces
exploit/linux/local/diamorphine_rootkit_signal_priv_esc.