sql >> データベース >  >> RDS >> Mysql

PDO-致命的なエラー:非オブジェクトでのメンバー関数fetch()の呼び出し

    コードには変数$usernameがあります 質問の上部にありますが、$userがあります 下部のセクションにあります。

    同じ変数を使用するつもりですか?

    $username = ($_GET ['user']);
    $sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count 
      FROM xf_user WHERE username='$user'" );
      //                           ^^ Should this ALSO be $username ?   
    $row = $sth->fetch();
    

    編集:さて、あなたはあなたのPDO::ATTR_EMULATE_PREPARESでかわいいだけです 。これを観察してください:

    データベースとテーブルの構造:

    Database changed
    mysql> show tables
        -> ;
    +----------------+
    | Tables_in_prep |
    +----------------+
    | users          |
    +----------------+
    1 row in set (0.00 sec)
    
    mysql> select * from users;
    +----+---------+--------+
    | id | userid  | pass   |
    +----+---------+--------+
    |  1 | Fluffeh | mypass |
    +----+---------+--------+
    1 row in set (0.00 sec)
    

    そして、PDO属性が追加された、自分のコードからコピーされたPHPコード:

    <?php
        //$username = ($_GET ['user']);
        $username="Fluffeh";
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    
    <?php
        //$username = ($_GET ['user']);
        $username="user2693017";
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    
    <?php
        //$username = ($_GET ['user']);
        $username="Oh my' or 1=1 or 'm=m";
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        $sth = $dbh->query( "SELECT userid, pass FROM users WHERE userid='$username'" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    
    <?php
        //$username = ($_GET ['user']);
        $username="(select id from users limit 1)";
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        $sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    
    <?php
        //$username = ($_GET ['user']);
        // Changed this one to be a non-string, you might be checking an ID instead.
        $username="(select id from users limit 1)";
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        $sth = $dbh->query( "SELECT userid, pass FROM users WHERE id=$username" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    
    <?php
        //$username = ($_GET ['user']);
        $username="bob'; drop table users; \  
        ";
        // This one is tricker to do in PHP code. I could easily enter this into a text field however.
    
        $dbh = new PDO('mysql:host=localhost;dbname=prep', 'prepared', 'example');
        $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
    
        //$sth = $dbh->query( "SELECT userid, pass FROM users WHERE id='$username'" );
        echo "Trying to use $username.\n";
        print_r($sth->fetch());
        echo "----------------------------------------\n\n";
    ?>
    

    そして出力:

        Trying to use Fluffeh.
    stdClass Object
    (
        [userid] => Fluffeh
        [pass] => mypass
    )
    ----------------------------------------
    
    
        Trying to use user2693017.
    ----------------------------------------
    
    
        Trying to use Oh my' or 1=1 or 'm=m.
    stdClass Object
    (
        [userid] => Fluffeh
        [pass] => mypass
    )
    ----------------------------------------
    
    
        Trying to use (select id from users limit 1).
    ----------------------------------------
    
    
        Trying to use (select id from users limit 1).
    stdClass Object
    (
        [userid] => Fluffeh
        [pass] => mypass
    )
    ----------------------------------------
    
    
        Trying to use bob'; drop table users; \  
            .
    ----------------------------------------
    

    ああ、私が最後のものを最後まで残した理由は、現在私のデータベースにあるこの出力です:

    mysql> show tables;
    Empty set (0.00 sec)
    

    はい、そうです、私はちょうどテーブルを落としました。繰り返しになりますが、私にはselectステートメントがあり、少し巧妙に、脳の半分と悪意のある人なら誰でもテキストフィールドに入力できる値を入力し、テーブルを削除しました。

    確かに、適切に設定している場合は、selectステートメントに別のユーザーを設定し、それらにselectのみを付与することもできます。 この種の事態の発生を阻止するためのデータベースからの権利-しかし正直に言うと...あなたはあなたではありませんか?

    そのエミュレーションを明確に設定するだけでは不十分です。真剣に、今すぐ行ってくださいその答えを読む 、コードを安全にしたい場合は、プリペアドステートメントを使用し、パラメータを使用します。



    1. テーブルからデータ行を削除した後、MySQLInnoDBがディスクスペースを解放しない

    2. MySQLで現在の日付と時刻を取得するにはどうすればよいですか?

    3. Spring DATA JPAを使用してカスタムクエリを作成しますか?

    4. SQL構文を使用して主キー制約を変更するにはどうすればよいですか?