Mcrypt is dead

PHP 7.2 zal dit jaar het licht zien. Een belangrijke wijziging op security-/beveiligingsgebied zal zijn dat de PHP-Mcrypt module komt te vervallen. Al enige tijd wordt er aangeraden om geen gebruik te maken van deze functies omdat ze onveilig en onbetrouwbaar zijn.

We hebben een paar steekproeven gedaan en zagen dat bepaalde applicaties toch nog gebruik van deze functies gebruik maken. In deze blog leggen we uit waarom je deze functies niet wilt gebruiken en wat de alternatieven zijn.

Waarom geen gebruik maken van Mcrypt?

Er zijn een paar belangrijke redenen om geen gebruik te willen maken van Mcrypt. Belangrijkste reden is dat het heel erg makkelijk is om onveilige cryptografie functies te gebruiken wat de veiligheid van je applicatie niet ten goede komt. Daarnaast is de libmcrypt (waar de PHP module gebruik van maakt) al een behoorlijke tijd niet meer in ontwikkeling (laatste wijziging in 2008!). Veel bugs en veiligheidsrisico’s zijn dus niet verholpen. Ook is de vrandom generator erg onbetrouwbaar, wat erg belangrijk is voor veilige encryptie.

Alternatieven Mcrypt

Er zijn een paar alternatieven om gebruik te maken van cryptografische functies in PHP welke wel veilig zijn:

libsodium

De meest efficiënte en veilige methode is gebruik te maken van de libsodium functies. Deze zal in PHP 7.2 als standaard worden meegeleverd. Vanaf versie PHP 7.0 kunt u bij ons ook al gebruik maken van libsodium door de ons meegeleverde Libsodium PECL extensie.

Defuse PHP-Encryption

Defuse’s php-encryption is een wrapper voor OpenSSL waardoor het lastig wordt om onveilige (standaard) PHP functies te aan te roepen. Als je applicatie composer gebruikt kun je deze zelf installeren (vanuit de directory waar je composer bestanden staan):

composer require defuse/php-encryption

Deze leveren wij ook standaard mee op onze HPW servers. In dat geval kan je de bibliotheek vanuit PHP aanroepen met:

require_once('defuse-crypto');

OpenSSL

Mocht je geen gebruik kunnen maken van bovenstaande functies dan kun je altijd terug vallen op de OpenSSL functies in PHP.

Planning

Vanaf PHP 7 is het gebruik van Mcrypt al deprecated. Dit betekent dat bij het gebruik van Mcrypt er een “DEPRECATED” melding in je PHP error log zal verschijnen. Deprecated wil zeggen dat code of een functionaliteit in een toekomstige versie uitgefaseerd zal worden. Vaak is het nog mogelijk om een aantal (kleine) versie updates gebruik te maken van een dergelijke functie. Maar vanaf PHP 7.2 zal Mcrypt niet meer aanwezig zijn en krijg je een “Fatal error: Call to undefined function mcrypt_*” ERROR bij het aanroepen van code met Mcrypt functies.

Pas je code aan

Applicaties zoals WordPress, Joomla en Magento maken, zeker in de recente versies, geen gebruik van Mcrypt functies. Hier hoef je dus zelf geen wijzigingen in aan te brengen. Als je gebruik maakt van een andere (eigen) PHP applicatie, dan is het raadzaam om je code te controleren of er niet toevallig gebruikt wordt gemaakt van onderstaande functies:

  • mcrypt_cfb
  • mcrypt_cbc
  • mcrypt_create_iv
  • mcrypt_decrypt
  • mcrypt_ecb
  • mcrypt_enc_get_algorithms_name
  • mcrypt_enc_get_block_size
  • mcrypt_enc_get_iv_size
  • mcrypt_enc_get_key_size
  • mcrypt_enc_get_modes_name
  • mcrypt_enc_get_supported_key_sizes
  • mcrypt_enc_is_block_algorithm_mode
  • mcrypt_enc_is_block_algorithm
  • mcrypt_enc_is_block_mode
  • mcrypt_enc_self_test
  • mcrypt_encrypt
  • mcrypt_generic_deinit
  • mcrypt_generic_end
  • mcrypt_generic_init
  • mcrypt_generic
  • mcrypt_get_block_size
  • mcrypt_get_cipher_name
  • mcrypt_get_iv_size
  • mcrypt_get_key_size
  • mcrypt_list_algorithms
  • mcrypt_list_modes
  • mcrypt_module_close
  • mcrypt_module_get_algo_block_size
  • mcrypt_module_get_algo_key_size
  • mcrypt_module_get_supported_key_sizes
  • mcrypt_module_is_block_algorithm_mode
  • mcrypt_module_is_block_algorithm
  • mcrypt_module_is_block_mode
  • mcrypt_module_openmcrypt_module_self_test
  • mcrypt_ofb
  • mdecrypt_generic

Met onderstaande shell opdracht kan je snel code vinden die gebruik maakt van Mcrypt functionaliteit. Je dient de onderstaande opdracht uit te voeren in de directory waar je applicatie zich bevindt (vaak webroot):

lh_mcrypt_functions=("mcrypt_encrypt" \
    "mcrypt_create_iv" \
    "mcrypt_cfb" \
    "mcrypt_cbc" \
    "mcrypt_create_iv" \
    "mcrypt_decrypt" \
    "mcrypt_ecb" \
    "mcrypt_enc_get_algorithms_name" \
    "mcrypt_enc_get_block_size" \
    "mcrypt_enc_get_iv_size" \
    "mcrypt_enc_get_key_size" \
    "mcrypt_enc_get_modes_name" \
    "mcrypt_enc_get_supported_key_sizes" \
    "mcrypt_enc_is_block_algorithm_mode" \
    "mcrypt_enc_is_block_algorithm" \
    "mcrypt_enc_is_block_mode" \
    "mcrypt_enc_self_test" \
    "mcrypt_encrypt" \
    "mcrypt_generic_deinit" \
    "mcrypt_generic_end" \
    "mcrypt_generic_init" \
    "mcrypt_generic" \
    "mcrypt_get_block_size" \
    "mcrypt_get_cipher_name" \
    "mcrypt_get_iv_size" \
    "mcrypt_get_key_size" \
    "mcrypt_list_algorithms" \
    "mcrypt_list_modes" \
    "mcrypt_module_close" \
    "mcrypt_module_get_algo_block_size" \
    "mcrypt_module_get_algo_key_size" \
    "mcrypt_module_get_supported_key_sizes" \
    "mcrypt_module_is_block_algorithm_mode" \
    "mcrypt_module_is_block_algorithm" \
    "mcrypt_module_is_block_mode" \
    "mcrypt_module_openmcrypt_module_self_test" \
    "mcrypt_ofb" \
    "mdecrypt_generic" \
)
find_lh_mcrypt_functions=$(echo ${lh_mcrypt_functions[@]}|tr " " "|")
grep -Ern --include "*.php" "$find_lh_mcrypt_functions" .