Operation of -real_escape_string

2

I have a login, that when I enter a username and password in a form and press "enter" and I have established the connection to the database, use the following line of code:

$pass = $mysqli->real_escape_string($_POST['txtpass']);

I am informing myself on the internet, but I do not understand the ->real_escape_string

what does it mean? How does it protect me from SQL-INJECTION?

I leave you the full piece of code

 <?php
if(isset($_POST['txtpass'])) 
{
    session_start();
    //variable de conexion: recibe dirección del host , usuario, contraseña y el nombre base de datos
    $mysqli = new mysqli("localhost", "root", "", "bdpersona") or die ("Error de conexion porque: ".$mysqli->connect_errno);
    // comprobar la conexión 
    if (mysqli_connect_errno()) 
    {
        printf("Falló la conexión: %s\n", mysqli_connect_error());
        exit();
    }

    $login = $mysqli->real_escape_string($_POST['txtlogin']);   
    $pass = $mysqli->real_escape_string($_POST['txtpass']);

    $resultado = $mysqli->query("SELECT * FROM tbusuario where login='$login' and pass='$pass' and activo!=0");
    $valida=$resultado->num_rows;
    if($valida != 0)
    {
        $datosUsu = $resultado->fetch_row();
        $_SESSION['nombreusu'] = $datosUsu[3];
        $_SESSION['perfil'] = $datosUsu[4];             
        echo "<META HTTP-EQUIV='Refresh' CONTENT='0; URL=listar.php'>";
    }
    else
    {
        echo 
        "<script> 
            var textnode = document.createTextNode('Usuario ó Password Incorrecto');
            document.getElementById('msg').appendChild(textnode);
        </script>";

    }   
}

? >

Thank you.

    
asked by Vidal 29.03.2018 в 13:28
source

1 answer

4

In many cases real_escape_string does not protect you from SQL injection, because there are substitution values that this function does not escape ( view this question and your answer ).

If you want to protect yourself from SQL Injection, use prepared queries.

It is very simple to do it. Read the comments in the code, where I'll explain what I've done:

 $login = $_POST['txtlogin'];  
 $pass  = $_POST['txtpass'];
/*
  * 1. Usamos prepare en lugar de query
  * 2. Cambiamos las variables por marcadores de posición ?
  *    Este es el núcleo del riesgo de inyección, porque las variables
  *    pueden ser concatenadas con código malicioso que se ejecutaría
  *    Nótese que he puesto las columnas explícitamente en el SELECT
  *    asumiendo que las mismas se llaman nombreusu y perfil ...
*/

$sql = "SELECT nombreusu, perfil FROM  registros where login=? and pass=? and activo!=0";
$stmt = $mysqli->prepare($sql);

/*
  * 3. Pasar parámetros separados  de la instrucción SQL
  *    Así se neutraliza la Inyección
  *    Para ello se usa un método llamado bind_param
  *    Las dos "ss" indican que hay dos columnas en la instrucción SQL de más arriba
  *    y que las mismas son del tipo String, por eso la s. 
  *    Si fueran números sería un i
  *    Luego se pasa el valor de esas variables, las cuales almacenamos desde el POST
  *    Es decir, tiene que haber tantos tipos de datos (en este caso "ss") 
  *    como columnas con marcadores de posición, 
  *    si por ejemplo la 1ª fuera String y la 2ª fuera número, entonces sería "si"
  *    y también tantas variables como columnas (dos variables en este caso)
  *    y tienen que ir en el orden en que aparecen en la consulta
*/
$stmt->bind_param("ss", $login,$pass);
$stmt->execute();

/*
  * 4. Usamos bind_result para almacenar en variables cada columna del SELECT
  *    Esto hay que hacerlo siempre ANTES de fetch...
  *    En bind_result debe habar tantas variables como columnas tenga el SELECT
  *    Nótese que store_result y num_rows ya no son necesarios, porque
  *    dado que fetch devolverá NULL si no hay datos, podemos aprovechar
  *    ese resultado para evaluar, optimizando así el código
*/

 $stmt->bind_result($nombreusu, $perfil);

if ($stmt->fetch())
{
    /* Aquí usaremos las variables de bind_result*/

    $_SESSION['nombreusu'] = $nombreusu;
    $_SESSION['perfil'] = $perfil;             
    echo "<META HTTP-EQUIV='Refresh' CONTENT='0; URL=listar.php'>";
}
else
{
    echo 
    "<script> 
        var textnode = document.createTextNode('Usuario ó Password Incorrecto');
        document.getElementById('msg').appendChild(textnode);
    </script>";

} 

P. D .: Given that apparently it is only a validation, I have changed the SELECT * for a SELECT COUNT(*) ... , since it is the most effective for these purposes.

    
answered by 29.03.2018 / 13:52
source