php

Codeigniter based No-CMS Admin Account Hijacking / RCE Exploit via Static Encryption Key

HELLO

This write-up we will analyze No-CMS web application which based on Codeigniter! Also we will continue to analyze Codeigniter too. If you haven’t read blog post about Codeigniter Object Injection possibilities before it’s time to read https://www.mehmetince.net/codeigniter-object-injection-vulnerability-via-encryption-key/ .  Because vulnerability use weakness of Codeigniter.

Summary of Codeigniter Object Injection Vulnerability

We are able to change session data if we already know encryption_key of application. That means we can add new fields into to the session array or we change it to whatever we want! So, application like No-CMS has to generate encryption_key on installation.

WARM-UP

Before go further I want to remind you some PHP behavior. Please read following code.

PHP interpreter will focus keys when you sum 2 array. In our example, first array have name  element, also second array have too. But values are diffirent. If you look at the output you will see name have ‘Linux’ value. Because PHP interpreter don’t change if relevant key already exist. It just adds  new ones. Keep this behavior of PHP in your mind because this will lead us to the Session Hijacking attacks!

Codeigniter Encrypt Cookie Enable/Disable

Codeigniter stores whole session array or part of it in cookie instead of hard-drive or database This is the reason why you might want to encrypt cookie values. In order to encrypt cookie values you need to set sess_encrypt_cookie to true which is FALSE with default configuration.

I said,  “part of session”. That means you can use database in order to store session data expect default fields like session_id, user-agent, ip-address etc.

No-CMS STATIC ENCRYPTION_KEY SYNDROME

I realized that No-CMS uses static encryption_key. We will have a look at installation process No-CMS . Modules located here No-CMS/modules/installer/models/install_model.php

Line between 1138 – 1144.

You see the encryption_key at 3th line. Key is namidanoregret .

Codeigniter Database For Session

You can store custom session field in database with $config[‘sess_use_database’]    = TRUE. But Codeigniter continue tı use whole serilize and unserialize mechanism with single distinction.

When sess_use_database enabled, Codeigniter only stores following array in cookie.

Rest of other field that has been added with Codeigniter are going to be in Database with serialized format. When Codeigniter try to read session,

first step ; CI does is decrypt cookie then unserialize and reach above array.

Second step ; Get session_id from array which is created at first step then execute query in order to fetch custom session fields. Unserialize returned string and sum them with following codes.

 $session array comes from, $custom_data array comes from second step. Now remember  WARM UP section.

No-CMS / Codeigniter Encryption Library

As I said before, No-CMS configured for encrypt session string. Now we will have a look at encryption methods

Now it’s time for continue to reading PHP codes. CI_Encryption class can be found following system/libraries/Encrypt.php.

Following codes constructer method Encryption class. It checks out mcrypt_encrypt native php method. If it exist then CI decide to use it on encryption process.

CI use 2 different encryption mechanism depends on PHP packages of your application server. If you did not install php5-mcrypt package on application server, CI will not be able to use mcrypt_encrypt method it needs to use something else.

Following codes grabbed from Encryption class. Encode method performs the data encryption and returns it as a string.

As you see, it is checking out _mcrypt_exists variable. If _mcrypt_exists assigned to the True by __construct method then it will use it. If it assined to the FALSE then CI have to use xor_encode.  So we don’t know which encryption method is enabled for target until decrypt cookie.

Lets see how codeigniter creates cookie string.

First of all, it check use database for session is enabled or not. If it is enabled then it only use default session field in order to send it to the client.

After that encrypt serialized session array and append hmac string to end of the cookie.

Now we will analyze how codeigniter reads cookie.

Now we see cookie authentication with hash_hmac. We alread now the encryption_key, session and sha1.

REVERSING No-CMS ENCRYPTED COOKIE

We know following informations.

to create session data.

  • Serialize session array and encrypt it via private_key.
  • Calculate hmac with private_key and append result to the end of the encrypted data.

to read session data.

  • Strip out hmac string from cookie.
  • Decrypt it private_key.
  • Add extra session array fields from database

Following string is real cookie has been generated by No-CMS.

Steps:

  •  Strip out last 40 character of Cookie. Because it belongs to hmac!
  • Decrypt rest part of cookie with mcrypt and xor. Because we dont know which one is used by target application.
  • Find session_id or ip_address strings result of decrypted string in order to identy encryption method. Because one of them has to be successfully decrypt it.
  • Unserialize session array.
  • Add extra fields into the array.
  • Serialize it.
  • Encrypt it detected encryption method via private_key.
  • Add result of the hmac to end of it.
  • Done.

EXPLOIT

I wrote exploit in order to generate new session data to gain administrator privileges. When you become an administrator you will be able to upload theme or add new administrator  account which lead to Remote Code Execution. Please analyze exploit codes.

This exploit does exactly same steps with above. It add cms_user_name = 1 and cms_user_id = 1 fields into the session array in order to become an administrator! Remember RECAP section we’ve learned behavior of PHP when it try to add one array to another one. Actually current user’s cms_user_name and cms_user_id values are different in database but it does not append them into to the session array because of that we already add them to session array by manually.

Also I’ve made a few modification on CI_ecnrypt class of Codeigniter in order to encrypt and decrypt cookie without having pain.

 RESULT

Encrypt cookie and store custom session field on database are enabled No-CMS but encryption_key is static! This is lead to gain administrator and have an access to Remote Code Execution via theme/module upload.

Also we can use unserialization of session array for Object Injection but I prefer to use Session Array Manipulation.

Feel free to write your ideas or ask a question via comment.

TIMELINE

Apr 21, 2014 at 20:17 PM = Vulnerability found.

Apr 22, 2014 at 1:27 AM = First contact with no-cms developers.

Apr 22, 2014 at 1:31 AM = Response from no-cms developer.

Apr 22, 2014 at 2:29AM = Vulnerability confirmed by developers.

Apr 22, 2014 at 04:37 = Vulnerability has been patch

  • mehmet ince

    Sorry but I have to keep it secret until they fix main site of no-cms because I realized that getnocms.com vulnerable too.

  • Very good write up. I never know about it before.
    I guess, for temporary fix, I can change the static-encryption-key mechanism.
    But a real fix should be done by changing the CodeIgniter mechanism.

    Thanks Mahmet. I’m glad you are the one who find this :)

    • mehmet ince

      Your welcome. I’m glad to contribute your open source application :)

  • KibodWapon

    good article!
    As I analyzed,your write up is no use for this CMS. And there are no dumplicated keys in the arrays of following code
    // Is there custom data? If so, add it to the main session array
    $row = $query->row();
    if ( ! empty($row->user_data))
    {
    $custom_data = $this->_unserialize($row->user_data);

    if (is_array($custom_data))
    {
    $session = $session + $custom_data;
    }
    }

    • mehmet ince

      Thank you. There is a duplicated key in $custom_data and $session. Both of them are array. $session array generated by client side encrypted cookie value. As an attacker we are able to decrypt it and add new key into to session array. Which means they gonna duplicate with $custom_data array which is comes from database and contains is admin True or False.