Insecure Hash Generation and Management in KirbyCMS Starterkit

kirby-locked-logo
Дата на публикуване 2018-06-27

Recently, during a white-box penetration test for one of our clients, we discovered several security issues related with the relatively popular KirbyCMS (Starterkit). The vulnerabilities are not of any sort of major security concern but are considered bad practice and can subsequently (in some cases) lead to a more severe vulnerability related to this.

The uncovered vulnerabilities are as follows:

  • Insecure hash generation and management;
  • Possibility for process timing attacks;
  • Insufficient entropy for quickRandom() (fall-back method);

Insecure Hash Generation and Management

The Kirby CMS utilizes bcrypt as its hash function. While bcrypt itself is a good choice, its implementation in this case is insecure and impractical. A snippet from the source code is given below.

// kirby/vendor/getkirby/toolkit/lib/password.php
public static function hash($plaintext) {
    $salt = substr(str_replace('+', '.', base64_encode(sha1(str::random(), true))), 0, 22);
    return crypt($plaintext, '$2a$10 . $salt);
}

There are several issues with the code and they are laid out below as follows:

  • The bcrypt signature $2a$ is deprecated due to high-bit attacks. Despite being highly difficult to execute such an attack, it is still a vulnerability. This is also specified in the PHP documentation.
  • The cost factor is hard-coded in the source code (rounds of blowfish encryption = 2cost factor). That is the value after the signature $10$. In this way a higher cost may not be picked unless manually changed.
  • Salt is generated using a custom function which is low on entropy thus making the salt generation predictable. In PHP7+, the parameter for specifying a salt is deprecated due to security concerns.

We benchmarked the entropy for several runtimes and the average entropy is 2.569 which is extremely low for cryptography usage in a high-level language such as PHP.

The results, at a recommended boundary of 11, are displayed below.

screenshotfrom2018-06-2714-38-22

Even when defining fall-backs, one should use a function that is cryptographically secure. Examples of such are random_int(), random_bytes(). A general assumption is that all functions that derive entropy from the underlying system pool are considered cryptographically secure.

Possibility for process timing attacks

As of version 2.1+, the Kirby CMS (starterkit) implements a non-constant-time algorithm (!= O(1)) for hash comparison within the Password class.

// vendor/getkirby/toolkit/lib/password.php
class Password {
  ...
  /**
   * Checks if a password matches the encrypted hash
   * 
   * @param string $plaintext
   * @param string $hash
   * @return boolean
   */
  public static function match($plaintext, $hash) {
    return crypt($plaintext, $hash) === $hash;
  }  
}

The execution time for a non-constant-time algorithm used in logical comparison depends linearly on the number of '1' bits in the string. While the number of '1' bits alone is not nearly enough information to make finding the string that return bool(true), repeated executions with the same (first) bits and different inputs can be used to perform statistical correlation analysis of timing information to recover the bool(true) value completely, even by a passive attacker.

An elementary example is presented below where a table chart with three run-time attempts has been recorded. Observing the data a pattern emerges under the Average column where a longer time of processing is noticeable for the 11th bit of our test. This would signify that the 11th bit is the most likely length of the bool(true) value (hashed password in this case).

screenshotfrom2018-06-2714-42-16_2

The Kirby (Starterkit) CMS is open-source and it could be freely audited by any third-party. This would pose a security threat under certain circumstances and in conjunction with a type of an exhaustive search attack, could lead to account takeover and possibility for privilege escalation.

Insufficient entropy for quickRandom() (fall-back method)

The quickRandom() method is a fall-back method that is used to generate cryptographically secure values, relying that they would be random enough so as not to be guessable. However, the quickRandom() method relies on PHP functions that are not to be used for cryptographic purposes:

public static function quickRandom($length = false, $type = 'alphaNum') {
	if(!$length) $length = rand(5, 10);
	$pool = static::pool($type, false);

	// catch invalid pools
	if(!$pool) return false;

	return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}

The functions used here are substr()str_shuffle()str_repeat(). It is explicitly noted in the PHP docs that str_shuffle() should not be used for generating cryptographically secure values:

CautionThis function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes() instead.

If you are using the KirbyCMS Starterkit, consider upgrading to the release candidate that has been published as of June 27, 2018. More information can be found at the vendor's official website: https://getkirby.com/changelog/kirby-2-5-11

Коментари

Няма публикувани коментари.

Нов коментар