¿Método seguro para almacenar objetos PHP en la base de datos MySQL?

3

¿Cómo guardo de forma segura los objetos PHP en una base de datos MySQL? Si usa las funciones serializar y deserializar, puede terminar con Inyecciones de objetos . ¿Existe un estándar predefinido sobre cómo manejar esto?

Tenga en cuenta que la inyección SQL = / = inyección de objetos! ¡Así que la DOP es una historia diferente aquí!

    
pregunta Critical joe 20.08.2016 - 14:49
fuente

3 respuestas

2

(No) Confiando en su base de datos

Debería poder confiar un poco en los datos de su base de datos, pero como defensa en profundidad es definitivamente mejor no confiar en ellos.

Por ejemplo, puede haber una inyección de SQL limitada, que permite insertar datos en la base de datos, pero nada más (quizás porque sus derechos de base de datos se administran correctamente).

Pero ahora, un atacante ganó la inyección de objetos, y quién sabe a qué puede conducir eso.

Integridad de los datos

Puede utilizar un HMAC para verificar la integridad de sus datos. De esa manera, puede estar seguro de que lo que entró en la base de datos es lo mismo que sale de ella (siempre que un atacante no tenga acceso a la clave, que por ejemplo puede estar almacenada en el código fuente).

Guardar unserialize

PHP7 permite un parámetro de opciones adicionales, en el que puede especificar qué clases no autorizadas puede crear.

Esto ya limita el poder de inyección de objetos. Un atacante aún puede sobrescribir los campos en el objeto en sí, lo que puede hacer de todos modos si asumimos el acceso de escritura en la base de datos, lo que puede no ser perjudicial, pero no pueden crear objetos arbitrarios.

Validación de entrada

También puede realizar una validación en los datos antes de enviarlos a unserialize, como recolectar todas las cadenas O:X y verificar si X es un objeto permitido.

Pero definitivamente recomendaría guardar la solución unserialize desde arriba.

Mitigación: no tener clases y funciones explotables

Es una buena idea verificar los datos y la autenticación en un nivel por función. Por ejemplo, no debe asumir simplemente que el campo x se puede confiar porque no está (actualmente) controlado por el usuario y, por lo tanto, es seguro pasarlo a Passthru.

No almacenar objetos

Si no tiene una buena razón para hacerlo, no debe almacenar objetos en la base de datos.

    
respondido por el tim 20.08.2016 - 15:52
fuente
1

Si no confía en su base de datos, la inyección de objetos es probablemente la menor de sus preocupaciones. El enlace que proporcionó específicamente se relaciona con los datos proporcionados por el usuario. Es un caso muy inusual en el que recibirá datos serializados de PHP de un cliente fuera de su pila de aplicaciones.

La solución es simple, y como siempre, verificar que los datos definidos por el usuario se encuentren dentro de los límites aceptables. Si bien puede usar un método mágico de activación para verificar la inyección inesperada de objetos (un poco más simple que implementar su propio deseralizador), una mejor solución es mantener una firma de los datos serializados y muy antes de deserializar:

 define('SERIALIZE_SALT', 's3cr3t5auce');

 function signed_unserialize($serialized, $signature)
 {
     if (sha1($serialized . SERIALIZE_SALT) === $signature) {
        return unserialize($serialized));
     } else {
        whatever();
        return new stdClass();
     }
    }

Sin embargo, creo que debo señalar que el uso de una base de datos relacional para almacenar objetos opacos (y, para el caso, ORM trivial) da como resultado aplicaciones que son difíciles de mantener y muy difíciles de escalar. Estos problemas, y su problema original se resuelven al normalizar su base de datos e implementar fábricas en su aplicación).

    
respondido por el symcbean 20.08.2016 - 15:15
fuente
0

La serialización de objetos en PHP es un campo de minas del que es mejor que te mantengas alejado. El manual viene con una gran advertencia roja:

  

¡Advertencia! No pase la entrada de usuario no confiable a unserialize() , independientemente del valor de las opciones de allowed_classes. La deserialización puede hacer que el código se cargue y se ejecute debido a la instanciación de objetos y la carga automática, y un usuario malintencionado puede explotar esto. Utilice un formato de intercambio de datos estándar y seguro, como JSON (a través de json_decode() y json_encode() ) si necesita pasar datos serializados al usuario.

     

Si necesita eliminar la serialización de datos serializados almacenados externamente, considere usar hash_hmac() para la validación de datos. Asegúrate de que nadie modifique los datos, excepto tú.

Siempre debe considerar los datos de la base de datos como datos no confiables. Por lo tanto, no debes llamar a unserialize en él. La solución HMAC mencionada anteriormente funcionaría si se realiza correctamente, pero es muy fácil obtener los detalles incorrectos aquí.

Por lo tanto, mi consejo es que solo bloquees esa función malvada unserialize en tu php.ini , y en su lugar, con JSON.

    
respondido por el Anders 28.02.2018 - 17:08
fuente

Lea otras preguntas en las etiquetas