2011-06-23 25 views
43

Tengo un sitio web simple donde establezco una conexión a un servidor Mysql usando PDO.¿Por qué PDO imprime mi contraseña cuando falla la conexión?

$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER', 
'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 

tuve algo de tráfico en mi sitio y el límite de conexiones servidores se alcanzó, y el sitio web lanza este error, con mi contraseña al descubierto en ella!

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[08004] [1040] Too many connections' in /home/domain/html/index.php:xxx Stack trace: #0 /home/domain/html/index.php(64): PDO->__construct('mysql:host=loca...', 'USER', 'SECRET', Array) #1 {main} thrown in /home/domain/html/index.php on line 64

Irónicamente me pasa a PDO por razones de seguridad, por lo que esto me impactó, porque este error exacto es algo que puede provocar muy fácilmente en la mayoría de los sitios que utilizan las inundaciones http simple.

Ahora he envuelto mi conexión en un bloque try/catch, pero aún así creo que esto es catastrófico.

Soy nuevo en PDO y, por lo tanto, mi pregunta es: ¿qué debo hacer para considerar que es seguro? ¿Cómo establezco una conexión de una manera segura? ¿Hay otros agujeros de seguridad conocidos como este que tengo que tener en cuenta?

+0

Ver: http://stackoverflow.com/questions/5811834/why -would-this-be-poor-php-code/5811853 # 5811853 Para un agujero cuando se usan nombres dinámicos de tabla/db/columna, y cómo tapar ese agujero. – Johan

+0

Estoy totalmente de acuerdo con desactivar los errores de producción, probar/atrapar y cosas por el estilo, pero considere si tiene un "equipo" de programadores en el extranjero donde la contraseña no debe ser conocida por los programadores "junior", esto es, como dijo una fuga de seguridad "catastrófica". Sin mencionar, los programadores novatos que no se preocupan por desactivar los errores. Dicho esto, estoy desconcertado por esta decisión de revelar la contraseña por error. – IMB

+0

Holy moly esto es ENFERMO! ¡OH DIOS MÍO! Esto es absolutamente escandaloso! Necesitas más votos positivos solo para mantener la calma y no entrar en CAPS RAGE. – Sharky

Respuesta

16

Debe tener display_errors = off en su PHP.ini de todos modos para evitar este problema. Los errores que revelan detalles como estos provienen de muchos lugares, además de PDO.

Sí, también debe tenerlo en un bloque try/catch.

También puede marcar $pdo->setAttribute(PDO::ERRMODE_SILENT), pero luego debe verificar los códigos de error manualmente en lugar de utilizar un bloque try/catch. Consulte http://php.net/manual/en/pdo.setattribute.php para obtener más constantes de error.

+12

bien lo entiendo, pero todavía creo que el valor predeterminado debería ser el lado seguro ... –

+2

@Joe, entonces deberías comentarlo con los desarrolladores de PDO. No veo ningún problema con que devuelva información de la pila como esta. Una vez que te das cuenta, no es un problema. Por supuesto, el try/catch será olvidado en algunas aplicaciones ... inevitablemente será un problema para algunos ... tienes razón al respecto. – Brad

+1

Ambas sugerencias no parecen funcionar para mí. Cuando la conexión falla, la pila de errores se imprime en la pantalla con la contraseña de texto sin formato visible. Estoy usando PHP ActiveRecord. –

6

Ok, esto me hizo reír un poco, el uso de informes de errores es para fines de depuración, le permite encontrar y solucionar problemas rápidamente.

Cuando se encuentre en un entorno en vivo, su servidor debe configurarse solo para el registro interno y no para la salida directa, por lo que básicamente deberá desactivar la salida de errores dentro de su php.ini.

display_errors = Off 

Pero mientras estás dentro de su entorno de prueba esta pila es simplemente una herramienta para ayudarle, y es configurable.

Cuando se producen errores dentro de un entorno en vivo, se registrarían, por lo que siempre debería verificar sus archivos de registro y luego corregirlos en consecuencia.

La gente puede especificar que puede gestionar errores dentro de su Aplicación PHP pero por preferencias personales Creo que esta es la manera incorrecta de hacerlo, configurar los archivos INI y config para su servidor web y MySQL/MsSQL dará como resultado una gestión más aguda.

Si su aplicación es una aplicación pública, también sería una buena idea manejar los errores dentro de la aplicación, ya que un gran porcentaje de clientes puede estar en hosting compartido y no tener acceso completo a las configuraciones del servidor.

+0

Usted no quiere contraseñas en sus archivos de registro, ya sea ... – HackSlash

7

solución simple para coger PDOException lanzada por DOP constructor:

try { 
    $dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER', 
    'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 
} catch (PDOException $e) { 
    throw new Exception('Could not connect to database'); 
} 
+0

... que deja a un desarrollador sin un mensaje de error que de otro modo los ayudaría a resolver un problema. –

+1

¿La excepción de obtención de "No se pudo conectar a la base de datos" deja al desarrollador sin información? No lo creo – Matthias

+3

El concepto base es malo. Nadie debe colocar una contraseña simple en un objeto y mantenerlo en la memoria. La solución correcta sería cambiar el código PDO, no poner la contraseña simple en el mensaje de una excepción. Considero esto como un error y un agujero de seguridad en PDO. – nagylzs

1

Nosotros usamos nombre de usuario y contraseñas codificada, y decodificar los del constructor de PDO, entonces cogemos el PDOException y lanzar una nueva PDOException con el viejo excepción es su mensaje, por lo que el seguimiento mostrará solo el nombre de usuario y la contraseña codificados.

Una buena biblioteca de cifrado para PHP es: a desactivar/php-cifrado

https://github.com/defuse/php-encryption

código Ejemplo:

<?php 
class myPDOWrapper extends PDO 
    { 

     public function __construct(string $dns, string $encodedUser, string $encodedPassword) 
     { 
      try { 
       parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword), 
        [ 
         PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 
        ] 
       ); 
      } 
      catch (PDOException $exception) { 
       throw new PDOException($exception->getMessage()); 
      } 
     } 

     private function decodeFunction(string $encoded): string 
     { 
      return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey()); 
     } 

     private function decodeKey(): \Defuse\Crypto\Key 
     { 
      static $key = null; 

      if(null === $key) { 
       $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY')); 
      } 

      return $key; 
     } 
    } 
Cuestiones relacionadas