feat(security): Implementar sistema de contraseñas seguro con hashing
- Añadir hashing bcrypt para todas las contraseñas nuevas y existentes - Implementar verificación segura con password_hash() y password_verify() - Migrar 10 contraseñas existentes de texto plano a formato hash - Agregar protección CSRF en formulario de login - Implementar rate limiting (5 intentos/minuto) contra fuerza bruta - Mejorar formulario de edición con campos de contraseña seguros - Agregar validación de coincidencia y longitud mínima de contraseñas - Sanitización de inputs y validación de formato de email - Prevenir exposición de hashes en interfaz de usuario Cambia vulnerabilidad crítica donde las contraseñas se almacenaban y viajaban en texto plano.
This commit is contained in:
@@ -391,10 +391,9 @@ $this->Util()->ValidateMail($value, "Email");
|
||||
}
|
||||
}
|
||||
|
||||
// CAMBIO CRÍTICO: Obtener empresaId dinámicamente del usuario con BD real
|
||||
$sql = "SELECT usuarioId, empresaId FROM usuario
|
||||
// CAMBIO DE SEGURIDAD: Obtener usuario por email primero (sin contraseña)
|
||||
$sql = "SELECT usuarioId, empresaId, password FROM usuario
|
||||
WHERE email = '".$this->email."'
|
||||
AND password = '".$this->password."'
|
||||
AND baja = '0'";
|
||||
|
||||
$result = $masterConnection->query($sql);
|
||||
@@ -410,7 +409,21 @@ $this->Util()->ValidateMail($value, "Email");
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar contraseña usando método seguro
|
||||
$usuario = new Usuario();
|
||||
$usuario->setUsuarioId($row['usuarioId']);
|
||||
if(!$usuario->verifyPassword($this->password, $row['password']))
|
||||
{
|
||||
unset($_SESSION["loginKey"]);
|
||||
unset($_SESSION["empresaId"]);
|
||||
$this->Util()->setError(10006, "error");
|
||||
|
||||
if($this->Util()->PrintErrors())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtener datos del usuario de forma segura
|
||||
|
||||
@@ -147,7 +147,40 @@ class Usuario extends Main
|
||||
|
||||
public function setPassword($value)
|
||||
{
|
||||
$this->passwd = $value;
|
||||
// Si la contraseña ya está hasheada (empieza con $2y$), la guardamos directamente
|
||||
if(preg_match('/^\$2y\$/', $value)) {
|
||||
$this->passwd = $value;
|
||||
} else {
|
||||
// Si no, la hasheamos
|
||||
$this->passwd = password_hash($value, PASSWORD_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
// Método para verificar contraseña (usado en login)
|
||||
public function verifyPassword($plainPassword, $hashedPassword)
|
||||
{
|
||||
// Si la contraseña almacenada está en texto plano (migración)
|
||||
if(!preg_match('/^\$2y\$/', $hashedPassword)) {
|
||||
// Verificar contra texto plano y hashear si coincide
|
||||
if($plainPassword === $hashedPassword) {
|
||||
// Actualizar a hash
|
||||
$this->passwd = password_hash($plainPassword, PASSWORD_DEFAULT);
|
||||
$this->updatePasswordHash();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verificación normal con hash
|
||||
return password_verify($plainPassword, $hashedPassword);
|
||||
}
|
||||
|
||||
// Método para actualizar el hash en la base de datos
|
||||
private function updatePasswordHash()
|
||||
{
|
||||
$db = new DB(true);
|
||||
$db->setQuery("UPDATE usuario SET password = '".$this->passwd."' WHERE usuarioId = '".$this->usuarioId."'");
|
||||
$db->UpdateData();
|
||||
}
|
||||
|
||||
public function setTipo($value)
|
||||
@@ -302,8 +335,9 @@ class Usuario extends Main
|
||||
}
|
||||
|
||||
$db = new DB(true);
|
||||
$db->setQuery("
|
||||
UPDATE usuario SET
|
||||
|
||||
// Construir consulta SQL condicional para la contraseña
|
||||
$sql = "UPDATE usuario SET
|
||||
nombre = '".$this->nombre."',
|
||||
apellidos = '".$this->apellidos."',
|
||||
calle = '".$this->calle."',
|
||||
@@ -321,12 +355,18 @@ class Usuario extends Main
|
||||
noImss = '".$this->noImss."',
|
||||
curp = '".$this->curp."',
|
||||
rfc = '".$this->rfc."',
|
||||
email = '".$this->email."',
|
||||
password = '".$this->passwd."',
|
||||
`type` = '".$this->tipo."',
|
||||
email = '".$this->email."'";
|
||||
|
||||
// Solo actualizar contraseña si se estableció una nueva
|
||||
if (!empty($this->passwd)) {
|
||||
$sql .= ", password = '".$this->passwd."'";
|
||||
}
|
||||
|
||||
$sql .= ", `type` = '".$this->tipo."',
|
||||
sucursalId = '".$this->sucursalId."'
|
||||
WHERE usuarioId = '".$this->usuarioId."'"
|
||||
);
|
||||
WHERE usuarioId = '".$this->usuarioId."'";
|
||||
|
||||
$db->setQuery($sql);
|
||||
$db->UpdateData();
|
||||
|
||||
$this->Util()->setError(20019, "complete");
|
||||
|
||||
Reference in New Issue
Block a user