Clase para manejar MySql evitando inyecciones de SQL
PHP March 23rd, 2007
Al escribir scripts para la web en php-mysql, una de las fallas más comunes en que la mayoría de la gente incurre es no validar apropiadamente la información proporcionada por el usuario del sistema, haciendo así vulnerable el sistema a lo que se conoce como ¨inyeccion de sql¨. Tomemos un ejemplo: Una consulta tipica creada por un usuario poco precavido para la autentificación de usuarios sería formada por concatenación y sería algo así como:
$sql = "select count(1) from usuarios where username = '" . $_POST["username"] . "' and password = '" . $_POST["password"] . "'";
Aquí vemos que la información enviada por el usuario es tomada tal cual y pasada por concatenación a la variable $sql , que almacena la consulta que se va a enviar hacia la base de datos. El usuario no se da cuenta que al hacer esto está dejando la puerta abierta al sistema. Definitivamente no es una buena idea. Veamos por que: supongamos que el usuario malicioso introduce como password “cualquier-password’ or 1=1; –“. El resultado de la concatenación seria
$sql = "select count(1) as count from usuarios where username = "cualquier-user' and password = 'cualquier-password' or 1=1;"
Notese que el incluir la condición or 1=1; hara que las condiciones especificadas sean evaluadas en su conjunto como verdaderas y la autenticación procederá. Después el usuario termina su sentencia con – para indicar que cualquier otra cosa más que siga sea considerada como comentario o ignorada.
La consulta resultará exitoso y dará entrada al sistema al usuario malicioso. Imagina las consecuencias que esto puede tener. Eso es solo un ejemplo de lo malo que puede resultar el no validar apropiadamente la información proveida por el usuario.
El canal de #php-es de la red FreeNode de IRC, canal en el cual asisto con regularidad, he visto que con frecuencia llega gente preguntando como evitar inyecciones de SQL en su sistema. En mi actividad como programador he tenido oportunidad de ver algunas clases escritas en PHP para facilitar la interacción con bases de datos (wrappers) para PostgreSQL y para Oracle. Esto me llevo a la idea de adaptar dicha funcionalidad en una clase en PHP para MySQL que permita contrarestar con facilidad el peligro de las inyecciones de SQL.
Dicha clase la puedes bajar aqui.
MODO DE USO
Usando el mismo ejemplo citado al principio tendriamos que hacer lo siguiente:
<?
include_once("clsDb.php"); //incluyendo la clase en cuestion
$db = new clsDb('localhost', 3306, 'midatabase', 'username', 'password', 0); //instanciando clase
$sql = "select count(1) as count from usuarios where username = :usuario and password = :password";
$r = $db->Parse($sql);
$r->BindByName(":username", $_POST["username"]);
$r->BindByName(":password", $_POST["password"]);
$r->Execute();
$row = $r->GetRow();
if ( $row->count == 1){
//se encontro un usuario con esa informacion de acceso.
} else {
//no se encontro ningun usuario con esa informacion de acceso
}
?>
En este ejemplo, vemos que la sentencia sql no es formada por concatenación como en el caso anterior, sino que ya viene completa, aunque viene escrita con un par de “marcadores” los cuales van a ser sustituidos con los valores apropiados, pero antes seran pasados por un proceso de sanitación que previene que el usuario malicioso del sistema pueda inyectar sql y hacer que el sistema haga otras cosas diferentes a las que fue diseñado.
Asi como se usan estos marcadores en combinacion con la funcion “BindByName” en una sentencia tipo select, se usan de igual manera para sentencias insert, update o delete. Es bastante sencillo. El chiste de esto es no confiar en que el usuario está dandonos un valor inofensivo, sino tomarlo como una potencial amenaza, y desactivar el peligro pasandolo por bindbyname. Espero le sea de utilidad a alguien.
December 2nd, 2009 at 5:47 pm
Gracias por la aportación ñ.ñ seguro para algo nos va a servir como ahorita jejejeje
Saludos
December 2nd, 2009 at 5:48 pm
Jajajaja xD no puedo descargarme la Clase T___T