Use of preg_replace invalidates password with SHA1

Asked

Viewed 252 times

4

Was using preg_replace, to avoid SQL Injection:

$senha = preg_replace('/[^[:alpha:]_]/', '',$_POST['senha']);

When comparing the $senha received by POST with the bank password (using SHA1) they are not compatible.

Someone tells me a better encoding that really avoids SQL Injection?

  • 1

    http://answall.com/questions/3864/como-prevenir-inje%C3%A7%C3%a3o-de-c%C3%b3digo-sql-no-meu-c%C3%b3digo-php/3869

  • 3

    I didn’t understand how regex solved the sql Injection problem, it seems that it created another.

  • 1

    Using PDO, or mysqi_* just create a placeholder type to inject a valid SQL, do not see why treat the data with preg_replace(). example in PDO: insert into tabela (senha) values (:senha_string) and in mysqi: insert into tabela (senha) values(?).

  • @Ivanferrer already do it with mysqli

  • 1

    But you agree that it is impossible to do sql Injection when vc declares the field $stmt->bindParam(':senha', $senha); the only thing you will do is validate the format, but you will never be injected a query that damages your system with it.

3 answers

3

It is obvious that the question has already been answered, but to supplement the comments, «Do not use sha1 to encrypt passwords», simply because it doesn’t protect you.

To handle validations, I recommend using the native validation functions & constants of PHP - PHP filters - or you can still read this answer to have more or less in mind how you should proceed with the rest.

Some examples of use:

2


There is no need to filter the string as it will be converted to a hash. The hash will convert everything, including escape characters that would allow sql injections or any other type of injections.

In short, don’t worry about anti-injection filters for this specific case.

See an example test to understand in practice:

$str = '\' delete from users; --\'';
echo sha1($str);

To be clearer, worry more about the validation of the received parameter:

$senha = null;
if (isset($_POST['senha']))
    $senha = trim($_POST['senha']);

if (!empty($senha))
    $senha = sha1(trim($_POST['senha']));
else
    echo 'senha não pode ser vazia'; exit;

2

A way to filter sha1 would be so:

function isSHA1($sha1) {
    return (bool) preg_match('/^[0-9a-f]{40}$/i', $sha1);
}

If you are using PDO for example, you can do so:

$dbh = new PDO("mysql:host=localhost;dbname=seubanco", $user, $pass);  

try {

      if (!isset($_POST['usuario'])) {
          throw new PDOException('Informe o nome de usuário!');
      }
      if (!isset($_POST['senha'])) {
          throw new PDOException('Informe a senha!');
      }

      if (!isUser($_POST['usuario'])) {
          //aqui você cria um método para tratar o usuário
          throw new PDOException('Informa um usuário válido!');
      }

      if (!isSHA1($_POST['senha'])) {
          throw new PDOException('A senha informada é inválida!');
      }

       $stmt = $dbh->prepare("
                            INSERT INTO usuarios (usuario, senha)
                            VALUES (:user,:pass)
                           "); 

       $usuario = $_POST['usuario'];
       $senha = $_POST['senha'];

       $stmt->bindParam(':user', $usuario);
       $stmt->bindParam(':pass', $senha);
       $stmt->execute();

} catch(PDOException $e) {
    echo $e->getMessage();
}

But there’s no need to validate sha1 for such a case, as the user will enter a normal password, and then it will be converted to sha1:

$dbh = new PDO("mysql:host=localhost;dbname=seubanco", $user, $pass);  

try {

      if (!isset($_POST['usuario'])) {
          throw new PDOException('Informe o nome de usuário!');
      }
      if (!isset($_POST['senha'])) {
          throw new PDOException('Informe a senha!');
      }

      if (!isUser($_POST['usuario'])) {
          //aqui você cria um método para tratar o usuário
          throw new PDOException('Informa um usuário válido!');
      }

       $stmt = $dbh->prepare("
                            INSERT INTO usuarios (usuario, senha)
                            VALUES (:user,:pass)
                           "); 

       $usuario = $_POST['usuario'];
      //convertendo a senha para sha1
       $senha = sha1($_POST['senha']);

       $stmt->bindParam(':user', $usuario);
       $stmt->bindParam(':pass', $senha);
       $stmt->execute();

} catch(PDOException $e) {
    echo $e->getMessage();
}

OBS: I do not recommend using hash with sha1() and neither md5(), although they are safe, as long as you include a token together with the password, both have collision failure: In this question, he talks more about the subject

A good alternative to password is the use of password_rash.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.