web-dev-qa-db-ja.com

このPHPログイン例のSQLインジェクションはありますか?

ログインフォームを書きたいのですが、Webから1つの例を入手しました。このコードにSQLインジェクションがあるかどうか知りたいですか?ある場合、エクスプロイトのWebフォームエントリはどのように見えるでしょうか?

これは私のフォームです:

<form method="post" action="">
    <dt class="title"><label for="username">name:</label></dt>
    <dt><input type="text" name="username" id="username"  size="50"></dt>
    <dt class="title"><label for="password">pass:</label></dt>
    <dt><input type="password" name="password" id="password" size="50"></dt>
    <input type="hidden" name="post" value="1" />
    <input type="submit" name="submit" value="submit" class="button">
</form>

これは私のチェックです:

if (($post[username]) AND ($post[password])) 
    {
        $query = 'SELECT * FROM `config` WHERE `config_admin_username`="'.$post[username].'" AND `config_admin_password`=MD5("'.$post[password].'") LIMIT 1';
        $sql_user_check = $db->fetch($query);
        if (!$sql_user_check) { 
            $error .= "Wrong Entry.<br />";
        } else {
            $_SESSION[admin] = 1;
            header("Location:index.php");
            exit;
        }
    }

Wamp 2.0iでphpmyadmin 3.2.0.1を使用しています

9
sorroshsaket

あなたは正しい場所に来ました。ようこそ ITセキュリティ

このコードにSQLインジェクションはありますか?

はい

そのエントリがある場合はどうなりますか?

username: [any username from your website]" /*
password: sux0r")*/ OR ("1"="1

それはこのクエリを実行します:

SELECT * FROM `config` 
WHERE `config_admin_username`="[any username from your website]" /* 
      AND `config_admin_password`=MD5("sux0r")*/ OR ("1"="1") LIMIT 1'

SQLエンジンが解析しないコメントアウトされた部分を削除すると、次の結果になります。

SELECT * FROM `config` 
WHERE `config_admin_username`="[any username from your website]" OR ("1"="1") LIMIT 1'

SQLクエリは、コメントアウトされた部分まで解析されます(私は/*および*/この例ではstart-comment/end-commentペアで、 MySQL を使用していると想定していますが、使用するRDBMSによって異なる場合があります)、パスワードチェックを完全に無効化します。 SQL内コメントがサポートされていない、または無効になっている場合でも、ログインを悪用するオプションは本当に無制限です。他に多くのことを最初に検討する必要があるので、パスワードハッシュアルゴリズムとしてMD5を選択することすらしません。ただし、パスワードハッシュに推奨されるハッシュアルゴリズムではありません。

このWebサイトにアクセスして、コードの安全性について自分自身に質問していることを確認しました。おめでとうございます、あなたはすでにより良いPHPプログラマーであり、これまでに得たことのないほとんどのプログラマーです!これで、既存の質問と回答からここで何を学ぶかはあなた次第です。いくつかのタグ考慮してください phpauthenticationweb-applicationhash 、...

19
TildalWave

TildalWaveにはすばらしい答えがありますが、SQLインジェクションにはすばらしい答えがありませんでした。準備されたステートメント。 Tildalが言ったように、ユーザー入力を含むステートメント全体が解析され、ステートメントの変数と定数部分の間に解析可能な区別はありません。解決策は、ステートメントの定数部分を変数プレースホルダー、次に変数とともに送信することです。 PDOは、SQLの対話に使用するものです。ここに私が使用する関数があります...

function _SQL_QUERY($_base_request, $_request_arguments)
{
                $_DB_USERNAME = "bob"; $_DB_PASSWORD="secret"; $_DB_LOCATION="localhost"; $_DB_NAME="MYWICKEDDATABASE"; $_DB_SERVER_TYPE="mysql";
                if(!isset($_DATABASE_CONNECTION))
                {
                        $_DATABASE_CONNECTION = new PDO("$_DB_SERVER_TYPE:dbname=$_DB_NAME;Host=$_DB_LOCATION;charset=utf8", $_DB_USERNAME, $_DB_PASSWORD);
                        $_DATABASE_CONNECTION->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
                }
                $__STMT = $_DATABASE_CONNECTION->prepare($_base_request);
                if($__STMT->execute($_request_arguments))
                {
                        return $__STMT;
                }
                else
                {
/*
        //Helpful ONLY when debugging!!!
                        echo 'ERROR</ br>';
                        echo $_base_request;
                        echo '</ br>';
                        print_r($__STMT->errorInfo());
                        print_r($_request_arguments);
                        die('</ br>');
*/
                        return false;
                }
}

それを使用するには、これを実行する必要があるだけです

_SQL_QUERY("Select * FROM names WHERE name=:var1 AND age=:var2", array('var1'=>'jim','var2'=>50));

これには多くの改善(主に機能的)が加えられますが、従来のSQL関数に対する大幅な改善です。ところで、データの挿入で行が失敗した場合、使用される方法によっては、バックアップと復元が実際に成功することを知っておくことが重要です。セキュリティに対するその動機でプログラミングを学ぶ人が増えれば、コードのセキュリティ監査を行うことに対する称賛。

9
David