Privilege Escalation Modules¶
Privilege Escalation is implemented using modules. Each privilege escalation
module is a sub-class of the EscalateModule
class. The escalate module’s
primary purpose is to enumerate possible escalation techniques. Techniques
are objects which implement specific escalation capabilities and can be put
together to form a fully-functional code execution primitive. Each technique
may implement file read, file write or shell/exec capabilities. The base
escalate module will collect all available techniques and attempt to use them
together to achieve the requested action.
Running an escalation module with no arguments simply returns an EscalateResult
which wraps a list of techniques. This result can be used to attempt file read,
file write or execution as the requested user. All escalate modules accept three
boolean arguments which indicate it should attempt one of read
, write
or
exec
. If any of these arguments are true, the requested action will be
attempted instead of returning the result.
When implementing an escalate module, any errors should be signaled by the
EscalateError
exception.
Automatic Privilege Escalation¶
The escalate.auto
module (aliased to simply escalate
) will attempt to use
any available module to escalate to the desired user. Further, it will recursively
attempt escalation through as many users as needed to find a path to the requested
user. This module simply aggregates the results from all available escalation
modules and then attempts the escalation with the available techniques. If direct
escalation to the requested user is not possible, it will attempt escalation to
eacho ther user available and recurse to find a path to the requested user.
This is the most common way to attempt privilege escalation, as it can quickly attempt multiple different escalation options through multiple users. However, if you know a likely vulnerability, you can execute an individual escalate module directly in the same way.
Any extra arguments passed to the escalate.auto
module will be passed on to
any module it executes. This allows modules with custom arguments to be included
in the automatic escalation attempts. However, this can be problematic. If two
modules have arguments with the same name and different required values, at least
one of them will fail to run. As a result, you cannot count on escalate.auto
to be able to attempt any module which requires custom arguments.
As with standard escalate modules, escalate.auto
will by default simply return
the escalate result containing all techniques it found. These techniques will span
multiple modules. This makes it easy to quickly enumerate all known possible
escalation paths.
Module Structure¶
Escalate modules at their core are a sub-class of BaseModule
. As such, you can
define custom arguments and platform requirements. If custom arguments are required,
you must include the EscalateModule
arguments in your definition as noted in the
class reference below.
class Module(EscalateModule):
""" Simple example module that does nothing. """
# Define supported platform(s)
PLATFORM = Platform.LINUX
# Default priority is 100. Higher value = lower priority. Must be > 0.
PRIORITY = 100
# Custom arguments. Remove this entirely if unneeded.
ARGUMENTS = {
**EscalateModule.ARGUMENTS,
"custom_arg": Argument(str),
}
def enumerate(self, user, custom_arg):
""" Implement a generator of Technique's """
# Technique implementation is what does the work of an
# escalate method. You should implement a technique class
# specific to your module.
# yield YourCustomTechnique(Capability.SHELL, "root", self)
def human_name(self, tech: YourCustomTechnique):
""" Create a pretty-printed representation of this module/technique """
return "a really cool custom technique"
Implementing A Technique¶
Techniques are the heart and soul of an escalation module. pwncat
uses
techniques with different capabilities together to attempt to perform various
actions. For example, if you request file read, pwncat
may use a exec
technique to gain a shell, and then read the file normally. Alternatively,
attempting exec
may require pwncat
to use read
and write
techniques to escalate privileges.
An individual technique is identified by a Capability
, a user name, and a
module. The capabilities are taken from pwncat.gtfobins
and include things
such as file read, file write or shell. There are associated methods within a
technique to execute these various capabilities and these are the methods you
must implement depending on the techniques supported capabilities. The module
is simply your module that created the technique. The user represents the name
of the user which this technique allows access as. For example, for a SETUID
binary, the user would be the owner of the binary itself.
Here is an example of a skeleton technique class:
# This decorator is not required, but if your technique may
# result in a EUID vs RUID mismatch, use this decorator to
# correct this issue automatically if needed.
@euid_fix
class YourCustomTechnique(Technique):
""" Implement the various capabilities your module provides """
def exec(self, binary: str) -> str:
""" Called for techniques which provide Capability.SHELL.
Execute the specified shell the other user, and return a
string which will exit the shell and return to the current
state. """
def write(self, filepath: str, data: bytes):
""" Called for techniques which provide Capability.WRITE.
Write ``data`` to the specified file as the other user. """
def read(self, filepath: str):
""" Called for techniques which provide Capability.READ.
Open the remote file for reading and return a file-like
object which yields it's contents. """
Utility Classes and Functions¶
-
pwncat.modules.escalate.
euid_fix
(technique_class)¶ Decorator for Technique classes which may end up with a RUID/EUID mismatch. This will check the resulting UID after to see if the change was affective and attempt to fix it. If the fix fails, then the resulting action is undone and an EscalateError is raised.
-
class
pwncat.modules.escalate.
GTFOTechnique
(target_user: str, module: pwncat.modules.escalate.EscalateModule, method: pwncat.gtfobins.MethodWrapper, **kwargs)¶ A technique which is based on a GTFO binary capability. This is mainly used for sudo and setuid techniques, but could theoretically be used for other techniques.
Parameters: - target_user (str) – The user which this techniques allows access as
- module (EscalateModule) – The module which generated this technique
- method (pwncat.gtfobins.MethodWrapper) – The GTFObins MethodWrapper
- kwargs – Arguments passed to the gtfobins
build
method.
-
class
pwncat.modules.escalate.
FileContentsResult
(filepath: str, pipe: pwncat.file.RemoteBinaryPipe, data: bytes = None)¶ Result which contains the contents of a file. This is the result returned from an
EscalateModule
when theread
parameter is true. It allows for the file to be used as a stream programmatically, and also nicely formats the file data if run from the prompt.-
category
¶ Meta private:
-
data
= None¶ The data that was read from the file. It is buffered here to allow multiple reads when the data is streamed back from the remote host. It should not be accessed directly, instead use the
stream
property to access a stream of data regardless of the state of the underlyingpipe
object.
-
description
¶ Meta private:
-
filepath
= None¶ Path to the file which this data came from
-
pipe
= None¶ Until it is read, this is a stream which will return the file data from the victim. It should not be used directly, and instead should be accessed through the
stream
property.
-
stream
¶ Access the file data. This should be used to access the data. The
pipe
anddata
properties should not be used. This is a file-like object which contains the raw file data.
-
title
¶ Meta private:
-
-
class
pwncat.modules.escalate.
EscalateChain
(user: str, chain: List[Tuple[pwncat.modules.escalate.Technique, str]])¶ Chain of techniques used to escalate. When escalating through multiple users, this allows
pwncat
to easily track the different techniques and users that were traversed. Whenexec
is used, this object is returned instead of theEscalateResult
object.It has methods to unwrap the escalations to return to the original user if needed.
-
add
(technique: pwncat.modules.escalate.Technique, exit_cmd: str)¶ Add a link in this chain.
-
category
¶ Meta private:
-
chain
= None¶ Chain of techniques used to escalate
-
description
¶ Meta private:
-
extend
(chain: pwncat.modules.escalate.EscalateChain)¶ Extend this chain with another chain. The two chains are concatenated.
-
pop
()¶ Exit and remove the last link in the chain
-
title
¶ Meta private:
-
unwrap
()¶ Exit each shell in the chain with the provided exit script. This should return the state of the remote shell to prior to escalation.
-
user
= None¶ Initial user before escalation
-
-
class
pwncat.modules.escalate.
EscalateResult
(techniques: Dict[str, List[pwncat.modules.escalate.Technique]])¶ The result of running an escalate module. This object contains all the enumerated techniques and provides an abstract way to employ the techniques to attempt privilege escalation. This is the meat and bones of the automatic escalation logic, and shouldn’t generally need to be modified. It will put together basic techniques into a working primitive.
Parameters: techniques (Dict[str, List[Technique]]) – List of techniques that were enumerated -
add
(technique: pwncat.modules.escalate.Technique)¶ Add a new technique to this result object
-
category
¶ EscalateResults are uncategorized
Meta private:
-
description
¶ Description of these results (list of techniques)
Meta private:
-
exec
(user: str, shell: str, progress)¶ Attempt to use all the techniques enumerated to execute a shell as the specified user.
Parameters: - user (str) – The user to execute a shell as
- shell (str) – The shell to execute
- progress – A rich Progress bar to update during escalation.
-
extend
(result: pwncat.modules.escalate.EscalateResult)¶ Extend this result with another escalation enumeration result. This allows you to enumerate multiple modules and utilize all their techniques together to perform escalation.
-
read
(user: str, filepath: str, progress, no_exec: bool = False)¶ Attempt to use all the techniques enumerated to read a file as the given user. This method returns a file-like object capable of reading the file.
Parameters: - user (str) – The user to read the file as
- filepath (str) – Path to the file to read
- progress – A rich Progress bar to update during escalation.
- no_exec (bool) – When true, do not attempt exec to write the file. This is needed when recursing automatically, and should normally be left as false.
-
techniques
= None¶ List of techniques available keyed by the user
-
title
¶ The title of the section when displayed on the terminal
Meta private:
-
write
(user: str, filepath: str, data: bytes, progress, no_exec: bool = False)¶ Attempt to use all the techniques enumerated to write to a file as the given user
Parameters: - user (str) – The user you would like to write a file as
- filepath (str) – The file you would like to write to
- data (bytes) – The data you would like to place in the file
- progress – A rich Progress bar to update during escalation.
- no_exec (bool) – When true, do not attempt exec to write the file. This is needed when recursing automatically, and should normally be left as false.
-
Technique Base Class¶
-
class
pwncat.modules.escalate.
Technique
(caps: pwncat.gtfobins.Capability, user: str, module: pwncat.modules.escalate.EscalateModule)¶ Describes a technique possible through some module.
Modules should subclass this class in order to implement their techniques. Only the methods corresponding to the returned caps need be implemented.
-
caps
= None¶ What capabilities this technique provides
-
exec
(binary: str)¶ Execute a shell as the specified user.
Parameters: binary (str) – the shell to execute Returns: A string which when sent over the socket exits this shell Return type: str
-
module
= None¶ The module which provides these capabilities
-
read
(filepath: str)¶ Read the given file as the specified user
Parameters: filepath (str) – path to the target file Returns: A file-like object representing the remote file Return type: File-like
-
user
= None¶ The user this provides access as
-
write
(filepath: str, data: bytes)¶ Write the given data to the specified file as another user.
Parameters: - filepath (str) – path to the target file
- data (bytes) – the data to write
-
Escalate Module Base Class¶
-
class
pwncat.modules.escalate.
EscalateModule
¶ The base module for all escalation modules. This module is responsible for enumerating
Technique
objects which can be used to attempt various escalation actions.With no arguments, a standard escalate module will return an
EscalateResult
object which contains all techniques enumerated and provides helper methods for programmatically performing escalation and combining results from multiple modules.Alternatively, the
exec
,write
, andread
arguments can be used to have the module automatically attempt the respective operation basedo on the arguments passed.-
PRIORITY
= 100¶ The priority of this escalation module. Values <= 0 are reserved. Indicates the order in which techniques are executed when attempting escalation. Lower values execute first.
-
enumerate
(**kwargs) → Generator[Technique, None, None]¶ Enumerate techniques for this module. Each technique must implement at least one capability, and all techniques will be used together to escalate privileges. Any custom arguments are passed to this method through keyword arguments. None of the default arguments are passed here.
-
human_name
(tech: pwncat.modules.escalate.Technique)¶ Defines the human readable name/description of this vuln
-
run
(user, exec, read, write, shell, path, data, **kwargs)¶ This method is not overriden by subclasses. Subclasses should should implement the
enumerate
method which yields techniques.Running a module results in an EnumerateResult object which can be formatted by the default run command or used to execute various privilege escalation primitives utilizing the techniques enumerated.
-