Nueva pregunta

Pregunta:

Fecha: 14-08-2016 15:49:57 (En Español)

Consulta sobre seguridad en bases de datos [PDO, Filtrado, sanitización de datos][Resuelta]

Hola mundo

Hace unos dias realice una pregunta sobre el tratamiento de caracteres especiales, en mi caso era sobre las \\ (doble backslash ) Problemas con el doble backslash \\ al insertar en la base de datos o imprimir en pantalla. El tema ha sido bien resulto con excelentes respuesta a lo cual he contribuido con mi aprendizaje con algunos ejemplos.

Superado este obstaculo me surgieron otras dudas relacionado a la seguridad, al ingresar o mostrar datos en una base de datos.
En la pregunta anterior se hablo sobre el uso de htmlspecialchars($string, ENT_QUOTES);
$tarea = <<<'EOF'
\\dcserver\public\documents\
\\dcserver\private\documents\myuser$
C:\users\miusuario\
URL: http://php.net/manual/es/language.types.string.php
NET SHARE
ADMIN$  C:\Windows  Admin remota
EOF;
$tarea = htmlspecialchars($tarea, ENT_QUOTES);// $tarea es una cadena que puede contener caracteres especiales como dobles backslash 
echo $tarea;


Consulta sobre seguridad:
Cuando utilizar bindParam y cuando no es necesario utilizarlo y directamente ejecutar el query tal cual se ha ingresado los datos.
1- Si no uso htmlspecialchars pero al guardar (INSERT) el dato en la tabla utilizó $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); con ello evito un intento de ataque?

2- Al recuperar el registro de la base de datos con SELECT tambien tengo que utilizar $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); para evitar una inyección de codigo?

Saludos


Etiquetas: MySQL - PHP - PHP PDO - Pregunta - Sanitización - Seguridad Votos: 4 - Respuestas: 11 - Vistas: 34 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 15-08-2016 21:21:19 Estoy armando un escenario para poder realizar las pruebas e ir ensayando las soluciones.
    Aun no he creado la base de datos, hasta ahora estoy haciendo el frontend aplicando lo que voy aprendiendo sobre bootstrap.
    En el backend hasta ahora son cosas sencillas, validaciones como que el email tenga formato de email, que los campos email, password no esten vacios o sean espacios y que existan las variables $_POST esperadas .
    En el frontend los campos son required. Con el inspector de elementos del navegador los pueden quitar para probar el funcionamiento del backend las validaciones.

    Luego creare la base de datos para ir trabajando sobre ello e ir aplicando lo que voy aprendiendo con las respuesta brindadas por uds.

    Les dejo el link del ejemplo online
    No tiene registro de usuarios, para loguearse pueden ingresar cualquier email y pass.
    Si esta en funcionamiento No cerrar sesión se mantiene la cookie por una hora a menos que cierren la sesión allí se destruye

    Saludos
      Votos: 3 - Link respuesta
     
  • Fecha: 16-08-2016 14:18:32 Buenas noches, buenísima idea!!! Estuve haciendo algunas cosas pero le voy a dedicar un poco más de tiempo. Lo único es que ingresé con este correo hi|@hkjhaskdh.coj.ar.ar.yt.r.ty. Como te darás cuenta es muy inventado. No se si esto te sirva. Seguiré con algunas cosas más

    Saludos
      Votos: 3 - Link respuesta
     
  • Fecha: 16-08-2016 16:59:22 Que bueno es saber Diego que te sumas a esta iniciativa.
    Todas tus sugerencias son bien recibidas.
    En cuanto a la validación de email he utilizado filter_var($email, FILTER_VALIDATE_EMAIL
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { // verifica que el email tenga el formato correcto
        $login = FALSE;
    }
    

    Tienes razón se valida un string hi|@hkjhaskdh.coj.ar.ar.yt.r.ty
    <?php
    $email="hi|@hkjhaskdh.coj.ar.ar.yt.r.ty";
    
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { 
        echo 'incorrecto';
    }else{
        
        echo 'correcto';
    }
    
    

    el demo online del codigo anterior

    No sé si existe una expresión regular sencilla capaz de validar emails que sean mas reales

    en cuanto tenga algo mas desarrollado compartiré los archivos

    saludos
      Votos: 1 - Link respuesta
     
  • Fecha: 17-08-2016 09:01:36 La parte de FILTER_VALIDATE_EMAIL, es correcta pues de hecho cumple con el estándar que menciona en la página.

    Ahora que aquí hay expresiones Logicas para utilizar: http://emailregex.com/

    Una clásica: La manera de validar un email, es enviando un código de confirmación a ese email, para confirmar el registro.
      Votos: 2 - Link respuesta
     
  • Fecha: 17-08-2016 15:07:21 Muchas gracias Porfirio por tu aporte.

    Aqui encontre un codigo que parece que cumple con el requisito de validar email.

    <?php
    $email1="hi|@hkjhaskdh.coj.ar.ar.yt.r.ty";
    $email2="usuario@dominio.com.ar";
    
    echo "El correo $email1 su validacion es: " .comp_mail($email1);
    echo ' - ';
    echo "El correo $email2 su validacion es: " .comp_mail($email2);
    
    function comp_mail($TestEmailAddress){
    if(preg_match("/^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$/", $TestEmailAddress)){
                return 'Correcto';
            } else {
                return 'Incorrecto';
            }
    }
    

    Resultado:
    El correo hi|@hkjhaskdh.coj.ar.ar.yt.r.ty su validacion es: Incorrecto - El correo usuario@dominio.com.ar su validacion es: Correcto

    Demo online.

    ¿Que les parece esa alternativa?

    Lo he implementado en el proyecto lo pueden probar online.

    Saludos
      Votos: 2 - Link respuesta
     
  •  
      3  
     
    Fecha: 17-08-2016 20:00:23 Hola, en cuestiones de filtrado de datos y de validaciones, siempre es bueno primero SANEAR ESTOS!

    La paranoia de seguridad en una aplicacion es algo que no viene nada mal, sabiendo y apegándose a las buenas practicas claro esta.

    Con respecto a tu primera pregunta:

    1- Si no uso htmlspecialchars pero al guardar (INSERT) el dato en la tabla utilizó $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); con ello evito un intento de ataque?
    Aqui lo primordial es tener en cuenta el objetivo del ingreso de datos por parte del cliente, por ejemplo si es necesario mantener ciertos tags como <p> o <strong> para que el cliente o usuario pueda postear un comentario con texto formateado a su gusto es bueno usar ya sea un tipo de saneamiento y reemplazo de tags por otros codigos que puedan interpretarse en el sistema como tal tag html, es decir tener un interprete de por medio y hacer un tipo de traduccion de los tags.
    Aunque PHP provee una funcion muy interesante, strip_tags(), segun el manual:
    Esta función intenta devolver un string con todos los bytes NULL y las etiquetas HTML y PHP retirados de un str dado.
    $text = '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>';
    echo strip_tags($text);
    // RESULTADO
    ////Test paragraph. Other text
    

    Cabe recalcar que aquella misma funcion recibe como segundo parametro las etiquetas que seran permitidas, ejemplo usando la variable anterior:
    // Permite <p> y <a>
    echo strip_tags($text, '<p><a>');
    // RESULTADO
    ////<p>Test paragraph.</p> <a href="#fragment">Other text</a>
    


    Pero es siempre importante tener en cuenta sanear antes de continuar con la validacion de los datos ingresados y la introduccion de cualquiera de estos a la base.

    PDO lo unico que provee con respecto a seguridad es la evasion de codigo malicioso que ponga en juego tu base de datos, es decir cualquier tipo de combinacion de caracteres que puedan hacer alguna SQL INJECTION, no provee seguridad con lo que respecta a ATAQUES XSS que son otros tipos de codigos afectan mucho mas directamente al DOM, como es el caso de JAVASCRIPT.
    Asi que lo mejor en estos casos es sanear, validar y luego insertar a la base, teniendo en cuenta que tipo de informacion deseas insertar en tu base.

    2- Al recuperar el registro de la base de datos con SELECT tambien tengo que utilizar $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); para evitar una inyección de codigo?
    Claro que si! Todo tipo de parametro que vaya a ser utilizado en una consulta es casi imprescindible mantenerlo limpio para poder proteger tus datos de la base.

    Con respecto a la validación de correos electronicos, como ya dije, una funcion para validar es siempre lo mejor, quizas PHP traiga de por si un tipo de funcion para esto, pero esta se basa en estandares, es decir no validara de forma personalizada como lo haria una que programes tu mismo, pero recuerda que antes de validar es preciso sanear.

    Saludos
      Votos: 3 - Link respuesta
     
  • Fecha: 23-08-2016 03:55:07 Podrias validar eso de que no vengan vacíos y lo del correo desde el frontal end, para que no tengas tanta carga con el servidor en el back end.

    También creo que podrías sustituir los [A-Za-z0-9]+ por el \w+ eso solo es para que quede más corto y legible, de hecho al final de la expresión utiliza esa misma.
      Votos: 1 - Link respuesta
     
  • Fecha: 23-08-2016 07:20:20 Buenos días, está bien validar los input y cualquier otra cosa que se requiera desde el cliente pero se debe validar también en el servidor. Es decir, si no está bien desde el cliente, no va a estar bien en el servidor pero puedo "saltear" el control en el cliente pensando que va a llegar bien al servidor y no va a ser así.

    Saludos

    DIEGO
      Votos: 3 - Link respuesta
     
  • Fecha: 23-08-2016 17:44:49 Muchas gracias por contribuir con los comentarios ;) con todos ellos aprendemos juntos.

    Israel: muchas gracias por tu sugerencia con el patrón para validar email sustituir los [A-Za-z0-9]+ por el \w+
    Comparto la modificación

    <?php
    $email1="hi|@hkjhaskdh.coj.ar.ar.yt.r.ty";
    $email2="usuario@dominio.com.ar";
    
    echo "El correo $email1 su validacion es: " .comp_mail($email1);
    echo ' - ';
    echo "El correo $email2 su validacion es: " .comp_mail($email2);
    
    function comp_mail($TestEmailAddress){
    if(preg_match("/^((\w+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$/", $TestEmailAddress)){
                return 'Correcto';
            } else {
                return 'Incorrecto';
            }
    }
    

    Código y ejecución Online

    Concuerdo con Diego, Siempre es bueno sanitizar, validar desde el lado del servidor ya que las validaciones del lado del cliente se puede evadir muy fácilmente, con desactivar javascript en el navegador y con el inspector de elementos que viene integrado con la mayoría de los navegadores se puede alterar el DOM por ejemplo podemos quitar los tags en HTML5 required etc

    Como primer capa de seguridad utilizar javascript y ciertos tags HTML5, luego siempre securizar del lado del servidor ya que este la última línea de defensa.


    Kip 13 muchisimas gracias por tu ejemplificadora explicación sobre seguridad sobre el tratamiento de datos en relación a la base de datos. Lo leeré con detenimiento y te comentare al respecto luego. No quería dejar pasar por alto el agradecimiento.

    Para todos uds por aportar con sus comentarios.

    Saludos
      Votos: 3 - Link respuesta
     
  • Fecha: 28-08-2016 16:39:49 Hola a todos, ultimamente estuve muy atareado con temas laborales por lo que no he tenido tiempo de participar activamente en más de una pregunta..., hoy me tome un rato para leer atentamente todas las respuestas, y la verdad muchachos cada día me sorprendo más de la excelencia y maravillosa calidad humana que hay por estos parajes, lo que hubiera dado por contar con gente como ustedes en mis inicios, felicitaciones a todos!

    Transcribo aquí mis respuestas dadas en el post original
    1- Pregunta: Si no uso htmlspecialchars pero al guardar (INSERT) el dato en la tabla utilizó $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); con ello evito un intento de ataque?
    Respuesta: no, con PDOStatement::bindParam salvas un posible inyección de código SQL en tu consulta (SQL Injection), pero no (por ejemplo) un ataque XSS.
    Esto que te comento es relativo, porque todo depende de como tratas el contenido ingresado por el usuario. Si lo guardas tal cual en la base de datos (cosa que yo no recomiendo) luego deberás tener mucho cuidad al momento de mostar ese contenido, porque si el usuario guardo, por ejemplo "<script>alert('ok');</script>" al momento de mostrarlo se podrá ejecutar el código (dependiendo si conviertes o no los caracteres especiales en entidades html).
    Es muy importante el uso de htmlspecialchars <-- esta función trabaja con los caracteres: & (et), " (comilla doble), ' (single quote), < (menor que), > (mayor que), no con todos. De hecho en la documentación oficial, cuando se explica el array $_POST esta puesta la función htmlspecialchars de forma implícita en el "Ejemplo #1 Ejemplo de $_POST"

    2- Pregunta: Al recuperar el registro de la base de datos con SELECT tambien tengo que utilizar $stmt->bindParam(':tarea', $tarea, PDO::PARAM_STR); para evitar una inyección de codigo?
    Respuesta: si y no, eso va a depender de si tienes el parámetro garantizado o no... digamoslo de otra forma, si el parámetro lo genera tu sistema no es necesario, porque se supone que tu generas el parámetro de una forma controlada/segura y no contendrá una inyección de código, ahora bien, si el parámetro es el resultado de algún ingreso de usuario, pues si, usa bindParam para evitar una inyección. No faltará el puritano que diga "usalo siempre" porque el parámetro puede no estar viniendo directamente del usuario, pero al verse comprometido tu sistema por alguna vulnerabilidad puede que el parámetro sea alterado, etc etc.....
    Otro motivo por el cual te puede interesar usar bindParam es por la performance en consultas (queries) repetitivas, ya que en la primera ejecución tendrás la consulta preparada y en las subsiguientes con parámetros distintos no será necesario preparar la consulta nuevamente.

    Tenía pensado aportar justamente lo que comenta Kip 13, pero no lo hago porque sería repetir mucho de lo dicho.

    Saludos a todos y como siempre buen código!

    PD: obviamente +1 para todos!
      Votos: 3 - Link respuesta
     
  • Fecha: 14-03-2017 19:21:08 En esta oportunidad desearía compartir con ustedes un artículo que desarrollé en mi blog y que ha sido bastante observado; sin duda será interezante para los que empiezan el trabajo con la API PDO de PHP, es un CRUD paso a paso; les dejo el link:
    CRUD con PDO de PHP
      Votos: 0 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión