lunes, 23 de agosto de 2010

Prepared Statements PHP y MySQL- Alta usuario

Anduve probando unas cosas en PHP, en estos dias que estaba mas libre con la facultad, y me decidi crear un alta de usuario, donde haya una seguridad relativamente alta.
Primero que nada use lo que se llama como Prepared Statements, que nos permite realizar una consulta al DBMS, pudiendo por asi decirlo, separar lo que ingresa el usuario del codigo mismo, es decir que el motor sabe que valor es ingresado por el usuario, con la ventaja pricipal en seguridad de que no pueden inyectar codigo arbitrario en la consulta conocido como SQL INJECTIO

Coloquemos un ejemplo de lo que seria una consulta con Prepared Statements, un consulta a un articulo de una noticia.

$mysqli = new mysqli('host', 'user', 'pass', 'db');
$stmt=$mysqli->prepare("SELECT * FROM NOTICIAS WHERE ID=?");
$stmt->bind_param('i', $_GET['id']);
$stmt->execute();

En la primer linea creamos el un objeto mysqli, en la segunda preparamos la consulta para enviar al motor, note que el valor que se espera se coloca con el caracter ?, tercera linea agrega la variable a la sentencia preparada, fijese que está el valor i, lo cual significa que lo que se espera será un entero. Tambien podemos usar s (string), d (double), b (binary data) dependiendo lo que se necesita.
En la cuarta linea ejecutamos el Statement Prepared. :)
En la sección de Prevencion de SQL INJECTION de la OWASP, lo tenemos como primer medida de seguridad. Lo bueno de esto es que el codigo no queda tan sucio, al filtrar todas las entradas del usuario con funciones como int(), settype(), is_numeric(), mysql_real_escape_string() etc.

El alta creado tiene las siguientes caracteristicas: La contraseña se encripta 3 veces en md5 (lo cual se puede cambiar desde el codigo), debe ser mayor a 7 caracteres, y debe contener al menos una mayuscula y un numero.
Este es el codigo con el formulario en HTML y el PHP.


<html>

Alta Usuario

<form action='' method='post'>
<br>
Nombre:
<br>
<input type='text' name='nombre'>
<br>
Email
<br>
<input type='text' name='email'>
<br>
Usuario:
<br>
<input type='text' name='user'>
<br>
Contraseña:
<br>
<input type='password' name='pass'>
<br>
<input type='submit' value='Enviar' name='enviar'>
</form>

function pass_cript($pass){
for($i=0;$i <3;$i++){ pass="md5($pass);" stmt=" $mysqli">prepare("SELECT usuario FROM usuarios WHERE usuario=?");
$stmt->bind_param('s', $usuario);
$stmt->execute();
$stmt->bind_result($result);
#tercer if
if($stmt->fetch()== false)
{
verificar_pass();
}
else {
echo "El usuario ya existe";
}
}

function alta(){

global $mysqli;
global $usuario;
global $password;
global $email;
global $nombre;
$password=pass_cript($password);
$stmt=$mysqli->prepare("INSERT INTO usuarios (usuario, password, Email, Nombre) VALUES (?, ?, ?, ?)");
// Bind your variables to replace the ?s
$stmt->bind_param('ssss', $usuario, $password, $email, $nombre);
// Execute query
$stmt->execute();
printf("%d Fila Insertada.\n", $stmt->affected_rows);
// Close statement object
$stmt->close();
echo "El usuario ".$usuario." ha sido dado de alta!!";
}

function verificar_pass(){
global $password;

if(strlen($password) > 7 )
{
if (preg_match('/[A-Z]+[0-9]+/', $password) || preg_match('/[0-9]+[A-Z]+/', $password))
{
alta();
}
else
{
echo "El password debe estar constituido por al menos una mayuscula y al menos un digito";
exit;
}
}
else
{
echo "El password debe ser mayor a 7 caracteres";

}
}




#Prepared Statements
$mysqli = new mysqli('host', 'user', 'pass', 'db');
if (mysqli_connect_errno())
{
printf("Can't connect to MySQL Server. Errorcode: %s\n", mysqli_connect_error());
exit;
}
#Primer if
if(!empty($_POST['enviar']))
{
#segundo if
if (isset($_POST['nombre']) && !empty($_POST['nombre']) && isset($_POST['email']) && !empty($_POST['email']) && isset($_POST['user']) && !empty($_POST['user']) && isset($_POST['pass']) && !empty($_POST['pass']))
{

$nombre=$_POST['nombre'];
$usuario=$_POST['user'];
$password=$_POST['pass'];
$email=$_POST['email'];
verificar_usuario();

}#cierre segundo if
else
{
echo "Debe rellenar los camposs gracias";
}
}#cierro primer if

?>


Voy a explicar lo que hace el codigo, osea su secuencia para que se entienda y luego los que quieren usarlo lo usen para sus
altas XD o para probar.
En la linea 105 es donde verifico que todos los datos del formulario esten definidos y que no esten en blanco, en caso afirmativo
tomo esos valores y voy a la función verificar_usuario().
Esta función lo que hace es verificar si el usuario que se quiere dar de alta existe en la base de datos,
en caso de que llegara a existir imprimira una leyenda con "El usuario ya existe", y se terminaria el proceso. En caso negativo se
se dirige a la función verificar_pass().
Esta función realiza el testeo de seguridad del password donde debe cumplir que: debe ser mayor a 7 caracteres y
debe contener al menos una mayuscula y un numero en el.
Cumpliendo estas restricciones en el password se dirige a la función alta(), que en la linea 57,
el valor de $password es pasado a a la función pass_cript(), para encriptarlo en una cantidad de 3 veces en MD5, luego basicamente
se realiza el INSERT INTO correspondiente al alta :).

Aca les dejo algunos enlaces para que sigan leyendo sobre Prepared Statemen

http://mattbango.com/notebook/web-development/prepared-statements-in-php-and-mysqli/
http://www.ultramegatech.com/blog/2009/07/using-mysql-prepared-statements-in-php/
http://www.hiteshagrawal.com/mysql/mysql-prepared-statement-in-php



Saludos

miércoles, 18 de agosto de 2010

JOINEA 2010


Bueno despues de mas de un mes sin postear, por motivos de la facultad y otras cosas vuelvo.

Este fin de semana se viene la JOINEA - Jornade de Integración, Extensión y Actualización de Estudiantes de Sistemas - el cual se realiza en Apostoles Misiones organizado por los chicos de la UNaM.
Hubo un llamado de papers, envie uno y quedo seleccionado, sobre Segridad Web: SQL injection y Directory Transversal, pero por motivos de tiempo en la expocicion lo reduje solamente a SQL Injection ya que se haria interminable.
Hay buen nivel de las expociciones, asi que seguro voy a ir a aprender mucho y conocer gente nueva el cual son los objetivos principales. Aqui les dejo el cronograma del evento.
Mañana a las 12 salimos de la Costanera, ya que el centro de estudiantes de la FA.CE.NA organizo el viaje para cualquiera a un costo accesible que incluye viaje, hospedaje y comida, en donde se lleno un colectivo con capacidad para 45 personas.
Aqui les dejo mi presentacion,




Saludos