Pregunta

Así que soy un desarrollador de PHP ligeramente experimentado y he estado 'haciendo la maldita cosa' desde 2007; sin embargo, todavía soy relativamente nulo cuando se trata de proteger mis aplicaciones. En la forma en que no sé realmente todo lo que sé, podría y debería.

He seleccionado Asegurando las aplicaciones web de PHP y estoy leyendo todo el camino. Está probando cosas a lo largo del camino. Tengo algunas preguntas para el grupo general de SO que se relacionan con la consulta de la base de datos (principalmente en mysql):

Al crear aplicaciones que ponen datos en una base de datos, ¿mysql_real_escape_string y la comprobación general (es_numérica, etc.) son suficientes en los datos de entrada? ¿Qué pasa con otros tipos de ataques diferentes de la inyección de SQL.

¿Alguien podría explicar los procedimientos almacenados y las declaraciones preparadas con un poco más de información que? usted las realiza y las llama. Me gustaría saber cómo funcionan, qué validación se realiza entre bastidores.

Trabajo en un entorno vinculado a php4 y php5 no es una opción por el momento. ¿Alguien más ha estado en esta posición antes, qué hiciste para asegurar tus aplicaciones mientras todos los chicos geniales están usando esa nueva y dulce interfaz mysqli?

¿Cuáles son algunas de las buenas prácticas generales que las personas consideran ventajosas, el énfasis en crear una infraestructura capaz de soportar las actualizaciones y las posibles migraciones (como mover php4 a php5)?

Nota: he tenido una búsqueda alrededor que no pudo encontrar nada similar a esto que haya afectado a la seguridad de php-mysql.

¿Fue útil?

Solución

Mis recomendaciones:

  1. abandone mysqli en favor de DOP (con el controlador mysql )
  2. utilice declaraciones preparadas paremeterizadas de DOP

Luego puedes hacer algo como:

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

PROs:

  1. ¡No más escapes manuales ya que PDO lo hace todo por ti!
  2. Es relativamente fácil cambiar los backends de la base de datos de repente.

CONs:

  • no puedo pensar en ninguna.

Otros consejos

La respuesta de Javier que tiene el enlace owasp es un buen comienzo.

Hay algunas cosas más que puedes hacer más:

  1. Con respecto a los ataques de inyección de SQL, puede escribir una función que eliminará las sentencias de SQL comunes de la entrada como " GOTA " o " BORRAR * DONDE " ;, de esta manera:

    * $ sqlarray = array (" DROP ", " o 1 = 1 ", " union select ", " SELECT * FROM " ;, select host ", " create table " ;, " DE los usuarios ", " usuarios DONDE "); *

    Luego escribe la función que verificará tu entrada contra esta matriz. Asegúrese de que cualquiera de las cosas dentro de $ sqlarray no sea una entrada común de sus usuarios. (No olvides usar strtolower en esto, gracias).

  2. No estoy seguro de si memcache funciona con PHP 4, pero puede implementar algo de protección contra correo no deseado con memcache permitiendo solo un cierto acceso remoto de IP a la página process.php X veces en el período de Y .

  3. Los privilegios son importantes. Si solo necesita privilegios de inserción (por ejemplo, procesamiento de pedidos), debe iniciar sesión en la base de datos en la página de proceso de pedido con un usuario que solo tenga privilegios de inserción y tal vez seleccione. Esto significa que incluso si una inyección de SQL se ha superado, solo podrían realizar consultas INSERT / SELECT y no eliminar ni reestructurar.

  4. Coloque los archivos de procesamiento de php importantes en un directorio como / include. Luego, no permita que todos los IPs accedan a ese directorio / include.

  5. Coloque un MD5 con sal con el agent + remoteip + your salt del usuario en la sesión del usuario y verifique en cada carga de página que el MD5 correcto está en su cookie.

  6. No permitir ciertos encabezados ( http://www.owasp.org/index.php / Testing_for_HTTP_Methods_and_XST ). No permitir PUT (si no necesita cargar archivos) / TRACE / CONNECT / DELETE headers.

Normalmente no trabajo con PHP, por lo que no puedo proporcionarle consejos específicamente orientados a sus requisitos, pero le sugiero que eche un vistazo a la página OWASP, en particular al informe de las 10 principales vulnerabilidades: http://www.owasp.org/index.php/Top_10_2007

En esa página, para cada vulnerabilidad, obtiene una lista de las cosas que puede hacer para evitar el problema en diferentes plataformas (.Net, Java, PHP, etc.)

Con respecto a las declaraciones preparadas, funcionan al permitir que el motor de la base de datos sepa cuántos parámetros y qué tipos esperar durante una consulta en particular, utilizando esta información, el motor puede comprender qué caracteres son parte del parámetro real y no algo que debería analizarse como SQL como un '(apóstrofe) como parte de los datos en lugar de' como un delimitador de cadena. Lo siento, no puedo proporcionar más información dirigida a PHP, pero espero que esto ayude.

AFAIK, PHP / mySQL no suele tener consultas parametrizadas.

El uso de sprintf () con mysql_real_escape_string () debería funcionar bastante bien. Si usa las cadenas de formato apropiadas para sprintf () (por ejemplo, "% d " para enteros), debería estar bastante seguro.

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

   <?php
    if (isset(

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_name']) && isset(

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_description']) && isset(

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['user_id'])) { // Connect $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password'); if(!is_resource($link)) { echo "Failed to connect to the server\n"; // ... log the error properly } else { // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON. if(get_magic_quotes_gpc()) { $product_name = stripslashes(

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_name']); $product_description = stripslashes(

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_description']); } else { $product_name =

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_name']; $product_description =

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['product_description']; } // Make a safe query $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)", mysql_real_escape_string($product_name, $link), mysql_real_escape_string($product_description, $link),

Puede que esté equivocado, pero no debería ser suficiente usar mysql_real_escape_string en los datos proporcionados por el usuario?

a menos que sean números, en cuyo caso debe asegurarse de que sean números, en su lugar, utilizando, por ejemplo, ctype_digit o is_numeric o sprintf (usando % d o % u forzar la entrada en un número).

Además, tener un usuario de mysql para sus scripts php que solo puede SELECCIONAR, INSERTAR, ACTUALIZAR y BORRAR es probablemente una buena idea ...


Ejemplo de php.net

  

Ejemplo # 3 A " Mejor práctica " consulta

     

El uso de mysql_real_escape_string () alrededor de cada variable evita la inyección de SQL. Este ejemplo muestra la "mejor práctica" Método para consultar una base de datos, independientemente de la configuración de Magic Quotes.

     

La consulta ahora se ejecutará correctamente y los ataques de Inyección SQL no funcionarán.

<*>
POST['user_id']); mysql_query($query, $link); if (mysql_affected_rows($link) > 0) { echo "Product inserted\n"; } } } else { echo "Fill the form properly\n"; }

Use procedimientos almacenados para cualquier actividad que implique escribir en la base de datos, y use parámetros de enlace para todas las selecciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top