Python’s Runtime Auditing

So let me explain it to you like this: imagine you have a web app running on Python and suddenly someone starts doing something weird with your code. Maybe they’re trying to execute malicious commands or access sensitive data. With Runtime Audit Hooks, you can monitor all the actions taken by the runtime (on behalf of the caller) and raise events whenever something interesting happens.

Here’s how it works: first, you add an auditing hook using either C code or Python code. Then, when certain operations occur within the Python runtime or standard library, a message is raised with all the relevant arguments. Hooks are added by calling PySys_AddAuditHook() from C (while the GIL is held) or sys.addaudithook() from Python code.

For example, let’s say you want to monitor when someone imports a module using Python code:

# Import the sys module
import sys

# Define a function to act as the audit hook
def my_hook(event, args):
    # Print the event that triggered the hook
    print("Event:", event)
    # Loop through the arguments and print each one
    for arg in args:
        print("\t", arg)

# Add the audit hook to the sys module
sys.addaudithook(my_hook)

# Now whenever a module is imported, the hook will be called with an "import" event and arguments like (<module 'os' from '/usr/lib/python3.8/os.pyc'), ('__loader__', <_frozen_importlib_external.SourceFileLoader object at 0x7fc51a9d46e0>), ...

# This script allows for monitoring of module imports using the sys module's audit hook functionality. The my_hook function is defined to print the event and arguments whenever the hook is triggered. The hook is then added to the sys module, allowing it to be called whenever a module is imported.

Or, let’s say you want to monitor when someone tries to execute a command using C code:

// This script adds an audit hook to monitor when someone tries to execute a command using C code.

// Include the necessary header file for Python
#include <Python.h>

// Define a function to act as the audit hook
static int my_hook(const char *event, PyObject *args) {
    // Print the event that triggered the hook
    printf("Event: %s\n", event);
    
    // Get the arguments from args and do something with them if necessary
    
    // Return 0 to indicate successful execution of the hook
    return 0;
}

// Add the audit hook to the Python system
int PySys_AddAuditHook(my_hook, NULL);

Now whenever a command is executed using Python’s built-in “os” module or any other module that uses the C library to execute commands (like subprocess), the hook will be called with an “exec” event and arguments like (“/bin/ls”, “-l”).

You can also use a Verified Open Hook to ensure that only approved code is executed. This allows Python embedders or system administrators to deploy builds of Python where auditing is always enabled. To do this, you set the handler using PyFile_SetOpenCodeHook() from C and then open files using io.open_code().

Here’s an example:

# Import necessary libraries
import os # Importing the os library to access and manipulate the operating system
from io import open_code # Importing the open_code function from the io library to open and execute code

# Define a function to handle file execution
def my_handler(path):
    # Check if the file is approved for execution
    # This function checks if the file path is within the specified PYTHONPATH directory
    # If it is, it returns the open_code function to execute the code
    # If not, it will not execute the code and will return an error
    if path.startswith(os.environ["PYTHONPATH"]):
        return open_code(path)
    else:
        print("File is not approved for execution.")

# Set the PYTHONPATH environment variable to the approved scripts directory
os.environ["PYTHONPATH"] = "/path/to/approved/scripts"

# Set the open code hook to use the my_handler function
PyFile_SetOpenCodeHook(my_handler, None) # This function sets the handler to ensure only approved code is executed

# Example of using the open_code function to execute a file
open_code("/path/to/approved/scripts/my_script.py") # This will execute the code in the specified file if it is within the PYTHONPATH directory

Now whenever a script is executed using Python’s built-in “open()” function or any other module that uses the C library to open files (like csv), the handler will be called with an absolute path and its return value will be returned directly. The returned object should be an open file-like object that supports reading raw bytes.

It may not sound like much at first glance, but trust me when I say this feature is a game changer for anyone who needs to monitor their code or ensure the security of their applications. And hey, if you ever need any help getting started with these hooks, just let us know we’re always here to lend a hand!

In addition to auditing individual events, Python also provides a way to monitor the entire runtime using a built-in module called audit. This allows you to detect when certain features are enabled or when hooks have been added and modify your behavior accordingly. For example:

# This script checks if the program is being audited using the built-in audit module in Python.

# Import the sys module to access system-specific parameters and functions.
import sys

# Import the isaudited function from the audit module.
from audit import isaudited

# Check if the program is being audited.
if isaudited():
    # If the program is being audited, print a message.
    print("We're being audited!")
else:
    # If the program is not being audited, do something else.
    # This section can be used to modify the program's behavior based on whether it is being audited or not.
    # For example, the program can log certain events or disable certain features if it is being audited.
    # This allows for better security and control over the program's runtime.

This code checks whether the current Python runtime is in “audit mode” and prints a message if it is. This can be useful for applications that need to behave differently when running under audit conditions, such as disabling certain features or logging more information.

Whether you’re monitoring individual events or the entire runtime, this feature provides a powerful tool for securing your code and ensuring its integrity. And with Python’s flexibility and ease of use, implementing these hooks is as simple as adding a few lines of code to your application. So why wait? Start auditing today!

SICORPS