8

ですから、私は少し経験豊富なphp開発者であり、2007年から「ひどいことをしている」のです。ただし、アプリケーションのセキュリティ保護に関しては、まだ比較的問題があります。自分ができること、すべきことをすべて知っているわけではないという意味で。

私はPHPWebアプリケーションの保護を取り上げ、その過程で物事をテストする方法を読んでいます。データベースクエリ(主にmysqlの下)に関連する一般的なSOグループについていくつか質問があります。

データベースにデータを配置するアプリを作成する場合、mysql_real_escape_stringと入力データの一般的なチェック(is_numericなど)で十分ですか?SQLインジェクションとは異なる他のタイプの攻撃についてはどうでしょうか。

誰かがストアドプロシージャとプリペアドステートメントを、あなたがそれらを作成して呼び出すよりも少し多くの情報で説明できますか?それらがどのように機能するのか、舞台裏でどのような検証が行われているのかを知りたいです。

私はphp4にバインドされた環境で作業していますが、当面はphp5はオプションではありません。他の誰かが以前にこの立場にあったことがありますが、すべてのクールな子供たちがその甘い新しいmysqliインターフェイスを使用している間に、アプリケーションを保護するために何をしましたか?

アップグレードや可能な移行(php4からphp5への移行など)に耐えられるインフラストラクチャの作成に重点を置いて、人々が有利であると考えている一般的なグッドプラクティスは何ですか。

注:検索したところ、php-mysqlのセキュリティに影響を与えるこれに類似したものは見つかりませんでした。

4

6 に答える 6

7

私の推奨事項:

  1. PDOを支持してmysqliを捨てます(mysqlドライバーを使用)
  2. PDO パラメータ化された準備済みステートメントを使用する

次に、次のようなことができます。

$pdo_obj = new PDO( 'mysql:server=localhost; dbname=mydatabase', 
                    $dbusername, $dbpassword );

$sql = 'SELECT column FROM table WHERE condition=:condition';
$params = array( ':condition' => 1 );

$statement = $pdo_obj->prepare( $sql, 
    array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY ) );
$statement->execute( $params );
$result = $statement->fetchAll( PDO::FETCH_ASSOC );

長所:

  1. PDO がすべてを実行するため、手動でエスケープする必要はもうありません。
  2. データベースのバックエンドを突然切り替えるのは比較的簡単です。

短所:

  • 私は何も考えられません。
于 2009-05-06T11:31:39.907 に答える
3

私は通常 PHP を扱っていないので、特にお客様の要件に的を絞ったアドバイスを提供することはできませんが、OWASP ページ、特にトップ 10 の脆弱性レポートをご覧になることをお勧めします: http://www.owasp.org /index.php/Top_10_2007

そのページでは、脆弱性ごとに、さまざまなプラットフォーム (.Net、Java、PHP など) で問題を回避するためにできることのリストを取得します。

準備されたステートメントに関しては、データベース エンジンに特定のクエリ中に期待されるパラメーターの数と型を知らせることで機能します。この情報を使用して、エンジンはどの文字が実際のパラメーターの一部であり、として解析する必要があるものではないかを理解できます。文字列区切り文字としての ' ではなく、データの一部としての ' (アポストロフィ) のような SQL。申し訳ありませんが、PHP を対象としたこれ以上の情報を提供することはできませんが、これがお役に立てば幸いです。

于 2009-05-05T21:42:08.297 に答える
2

私の知る限り、PHP/mySQL には通常、パラメーター化されたクエリはありません。

sprintf()withを使用すると、mysql_real_escape_string()かなりうまく機能するはずです。適切なフォーマット文字列sprintf()(整数の場合は "%d" など) を使用すると、かなり安全になります。

于 2009-05-06T12:53:27.310 に答える
1

私は間違っているかもしれませんがmysql_real_escape_string、ユーザー提供のデータで使用するのに十分ではありませんか?

それらが数値である場合を除き、その場合は、たとえばctype_digitまたはis_numericまたはを使用して、実際に数値であることを確認する必要がありますsprintf%dまたはを使用%uして数値への入力を強制します)。

また、SELECT、INSERT、UPDATE、および DELETE のみを実行できる php スクリプト用の serarate mysql ユーザーを持つことは、おそらく良い考えです...


php.net の例

例 3 「ベスト プラクティス」クエリ

各変数の周りで mysql_real_escape_string() を使用すると、SQL インジェクションが防止されます。この例は、マジック クォートの設定とは関係なく、データベースをクエリするための「ベスト プラクティス」の方法を示しています。

クエリが正しく実行されるようになり、SQL インジェクション攻撃が機能しなくなります。

   <?php
    if (isset($_POST['product_name']) && isset($_POST['product_description']) && isset($_POST['user_id'])) {
        // Connect

        $link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password');

        if(!is_resource($link)) {

            echo "Failed to connect to the server\n";
            // ... log the error properly

        } else {

            // Reverse magic_quotes_gpc/magic_quotes_sybase effects on those vars if ON.

            if(get_magic_quotes_gpc()) {
                $product_name        = stripslashes($_POST['product_name']);
                $product_description = stripslashes($_POST['product_description']);
            } else {
                $product_name        = $_POST['product_name'];
                $product_description = $_POST['product_description'];
            }

            // Make a safe query
            $query = sprintf("INSERT INTO products (`name`, `description`, `user_id`) VALUES ('%s', '%s', %d)",
                        mysql_real_escape_string($product_name, $link),
                        mysql_real_escape_string($product_description, $link),
                        $_POST['user_id']);

            mysql_query($query, $link);

            if (mysql_affected_rows($link) > 0) {
                echo "Product inserted\n";
            }
        }
    } else {
        echo "Fill the form properly\n";
    }
于 2009-05-06T08:54:57.710 に答える
0

DB への書き込みを伴うアクティビティにはストアド プロシージャを使用し、すべての選択にはバインド パラメータを使用します。

于 2009-05-06T08:47:28.040 に答える