-1

SQL インジェクションなどの攻撃を防ぐためにパスワードを暗号化したいのですが、PHP で暗号化機能を使用しましたが、それを使用してパスワードを暗号化する方法がわかりません。

データベースに接続してクエリを使用できるように、ユーザー テーブル内の各パスワードを暗号化したいのですが、うまくいきません。

誰でも私を助けてもらえますか?

ecnription.php

<?php
require_once('include/connect.php');

if(isset($_SESSION['user_id']))
{
    $id= $_SESSION['user_id'];


}
$sql = mysql_query("SELECT password FROM user WHERE user_id= '$id'")or die(mysql_error());
while($row = mysql_fetch_array($sql))
{
    $enc_pass= $row['password'];

}

error_reporting(0);

class Encryption
{
    const CYPHER = MCRYPT_RIJNDAEL_256;
    const MODE   = MCRYPT_MODE_CBC;
    const KEY    = 'somesecretphrase';

    public function encrypt($plaintext)
    {
        $td = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, self::KEY, $iv);
        $crypttext = mcrypt_generic($td, $plaintext);
        mcrypt_generic_deinit($td);
        return base64_encode($iv.$crypttext);
    }

    public function decrypt($crypttext)
    {
        $crypttext = base64_decode($crypttext);
        $plaintext = '';
        $td        = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
        $ivsize    = mcrypt_enc_get_iv_size($td);
        $iv        = substr($crypttext, 0, $ivsize);
        $crypttext = substr($crypttext, $ivsize);
        if ($iv)
        {
            mcrypt_generic_init($td, self::KEY, $iv);
            $plaintext = mdecrypt_generic($td, $crypttext);
        }
        return trim($plaintext);
    }
}


$encrypted_string = Encryption::encrypt($enc_pass); 
$decrypted_string = Encryption::decrypt($encrypted_string);

echo $encrypted_string . "<br>" . PHP_EOL;
var_dump($id);
echo $decrypted_string . "<br>" . PHP_EOL;
4

1 に答える 1

4

実際、パスワード暗号化は mysql インジェクションとは何の共通点もありません。これらのことは別々に行う必要があります (MUST!)。

パスワードの暗号化 (この場合はハッシュ) により、データベースにアクセスした可能性のあるハッカーがユーザーのパスワードを使用できなくなります。ハッシュ関数は 1 つの方法です。パスワードからハッシュを作成できますが、ハッシュからパスワードを作成することはできません。ハッシュからパスワードを取得する唯一の方法は、可能なすべての文字の組み合わせをハッシュし、このハッシュが db の this と等しいかどうかを確認することです。ほとんどの uf ユーザーは、php で単純な md5() または sha256() 関数を使用します。実際には機能しますが、これらの関数の問題はその単純さにあります。ファイルのチェックサムを計算するために作成されたので、高速だったに違いありません。そのため、総当たり攻撃が容易になります。ブルートフォースになるのを避けるために、次のことができます。

a) 「salt」を追加し、md5 / sha256 を使用し続けます。Salt は、ハッシュする前にユーザー パスワードに追加されるランダムな文字列です。たとえば、「パスワード」の近くに、データベースに追加の列を作成する必要があります。各ユーザーは、少なくとも 32 文字の長さのソルトをランダムに取得する必要があります。「パスワード」フィールドは、md5(salt . users_password) を使用して作成されます。ログイン時にパスワードを確認する場合は、データベースからパスワードとソルト フィールドを取得し、投稿からユーザーのパスワードを取得して、md5(salt . user_password_from_post) をデータベースの「password」と比較します。ユーザーのパスワードが短くても、ソルトのために長くて複雑になります。すべての 8 文字のパスワードをクラック/ブルート フォースするには、~80^8 ハッシュしか必要ありませんが、ソルト化された 8 文字のパスワードをブルート フォースするには、80^32 倍の ~80^40 が必要です。

b) フグ アルゴリズムを使用するhttp://php.net/manual/en/function.crypt.php フグは、最初からパスワードを暗号化するために作成されました。ソルトも使用する必要がありますが、ハッシュの複雑さを示す「コスト」パラメーターを指定することもできます。より複雑 = パスワード チェックのたびに CPU 使用率が高くなりますが、安全性も高くなります。フグ、16 バイトのソルト、および少なくとも 10 のコストで保護されたパスワードは安全であると言われています。

sql-injected を回避するには、クエリに渡されるすべてのパラメーターをエスケープする必要があります。mysql_real_escape_string() があなたの味方になります。

$Query = sprintf("SELECT UserId, Password, Salt FROM Users WHERE Username='%s'", mysql_real_escape_string($_POST['Username']));
mysql_query($Query);

もし

$_POST['Username'] = "'; DROP TABLE Users; --"

エスケープなしのクエリは次のようになります。

"SELECT UserId, Password, Salt FROM Users WHERE Username=''; DROP TABLE Users; --'

このクエリにより、どのユーザーも問題なくデータベースを破棄できます。mysql_real_escape_string を使用すると、クエリは次のようになります。

"SELECT UserId, Password, Salt FROM Users WHERE Username='\'; DROP TABLE Users; --'

これでデータベースは安全です。

パスワードをチェックするための完全なコード (DB に username(128)、password(32)、salt(32) が必要です):

function CheckPassword($Username, $Password)
{
    list($Count) = mysql_fetch_array(mysql_query(sprintf("SELECT COUNT(*) FROM Users WHERE Username='%s'", mysql_real_escape_string($Username))));
    if(!$Count)
        return false; //No such user
    list($Password_Db, $Salt) = mysql_fetch_array(mysql_query(sprintf("SELECT Password, Salt FROM Users WHERE Username='%s'", mysql_real_escape_string($Username))));
    if(md5($Salt . $Password) == $Password_Db)
        return true;
    return false;
}
于 2013-05-11T11:47:24.750 に答える