Persistent Credential Theft with Authorization Plugins
Archived: 2026-04-06 02:01:32 UTC
Credential theft is often one of the first tactics leveraged by attackers once they’ve escalated privileges on a
victim’s machine. Credential theft on OSX has become more difficult with the introduction of System Integrity
Protection (SIP). Attackers can no longer use methods such as extracting the master keys from the securityd
process and decrypting the victim’s login keychain. An example of this can be seen here. SIP prevents any user
(even root) from modifying system files, directories, and processes. This might lead an attacker to use other
methods for credential theft including keylogging, prompting the user for credentials, or triaging the local file
system for plaintext credentials. However, there is another alternative called authorization plugins.
Authorization plugins are used to extend the authorization services API and implement mechanisms that are not
natively supported by the OS. A legitimate use case would be implementing multi-factor authentication with 3rd
party software such as Duo. Each plugin can have several mechanisms, or functions contained within the plugin
that implement custom logic to perform authorization. These mechanisms are also present in the policy database.
This database contains definitions for various authorization rights. The definition for a particular authorization
right can reference several mechanisms, each paired with their corresponding authorization plugin. Apple briefly
describes how this works during the logon process here. Essentially, the loginwindow process tries to obtain the
system.login.console right. The definition in the policy database lists several mechanisms that are executed when
this happens. A custom plugin, along with its mechanism, can be inserted into this list. The position of the entry in
this list will determine when it will be executed and should be determined based on how the plugin will interact
with the OS during the logon process. Additionally, a plugin can be configured to run in a privileged or un-privileged context. This is indicated by the entry string within the policy database. For privileged execution,
“,privileged” will need to be appended to the mechanism entry. An author may choose to use an unprivileged
plugin if they wish to access the UI and present a prompt to the user. Additional information on plugin context
issues can be found here.
An interesting (especially for attackers) feature of authorization plugins is the ability to pass context values
between plugins. These values contain important details about the user, including, the home directory, uid, and
even the password in clear-text. This feature exists so that developers who wish to utilize both a privileged and un-privileged plugin, can share data between the two in a relatively easy way. Authorization plugins are an ideal
credential theft and persistence mechanism for attackers. Persistent credential theft with the ability to execute code
at any point during the login process is invaluable. Installing an authorization plugin is a relatively easy process,
which we’ll cover in the next section.
Installation
Authorization plugins are comprised of two components; the bundle file that contains all of the plugins code, on
disk, and an entry into the authorization database. The authorization database is used by the security server to
authorize specific rights for a given user, based on rules/policies contained within the database. Applications may
change the rules at any given time using the AuthorizationRightSet, AuthorizationRightGet, and
https://xorrior.com/persistent-credential-theft/
Page 1 of 4
AuthorizationRightRemove API calls. When adding an entry to the database, the AuthorizationRightSet function
should be called with a reference to a NSDictionary containing keys and values for each authentication
mechanism. An example is shown in the Apple documentation here. Alternatively, the AuthorizationRightGet
function can be used to obtain the NSDictionary value for an existing right. Then modify the dictionary and add an
entry for the custom authorization plugin using the AuthorizationRightSet function. A python example of this can
be seen here.
The authorization database can also be modified via the security command line tool. If an attacker wanted to add a
malicious plugin to the system.login.console policy, they would need to first read the policy from the authorization
database into a plist file:
security authorizationdb read system.login.console >> system.login.console.plist
Then insert their bundle as one of the mechanisms in the following format:
[Plugin Name]:auth,privileged
PlistBuddy can also do this with the following command:
/usr/libexec/PlistBuddy -c “add :mechanisms:[HomeDir Offset] string [bundlename]:login,privileged”