4

次の PHP コードを実行しようとすると、

オブジェクト以外でメンバー関数 fetch() を呼び出します。

なぜなのかご存知ですか?別のサイトで同じコードを使用していますが、問題なく動作しています。

<?php
$username = ($_GET ['user']);
try {
    $dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');    
} catch (PDOException $e) {
    echo $e->getMessage();
}
$sth = $dbh->query( "SELECT user, captcha 
    FROM xf_captcha WHERE user='$username'" );
print_r($sth->fetch());
?>

編集:

$sth = $dbh->query( "SELECT username, user_state, last_activity, alerts_unread, conversations_unread, message_count 
    FROM xf_user WHERE username='$user'" );
$row = $sth->fetch();

編集2:

これは安全に見えますか?もっとやるべきですか?

<?php
$username = ($_GET ['user']);
try {
    $dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');
} catch (PDOException $e) {
    echo $e->getMessage();
}
$sth = $dbh->prepare("SELECT username, captcha, timestamp 
    FROM xf_captcha 
    WHERE username = :username", array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $username));
print_r($sth->fetch());
?>
4

3 に答える 3

3

コード$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; \  
        .
----------------------------------------

ああ、最後のものを LAST まで残した理由は、データベースにあるこの出力です。

mysql> show tables;
Empty set (0.00 sec)

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

確かに、適切に設定している場合は、選択ステートメント用に別のユーザーを設定し、データベースからの権限のみを付与してselect、この種のことが起こらないようにすることもできますが、正直に言うと...じゃないですか?

エミュレーションが不十分であることを明確に設定します。真剣に、コードを安全にしたい場合は、その答えを読んで、準備されたステートメントを使用し、paramsを使用してください。

于 2013-09-26T01:18:37.843 に答える
0

Execute ステートメントはどこで呼び出されていますか? これもあなたの中にあります->queryか?より良いクエリ構築のために以下を使用することを考えていない場合:

<?php
            $username = ($_GET['user']);
            try {
                $dbh = new PDO("mysql:host=localhost;dbname=***", '***', '***');    
            } catch (PDOException $e) {
                echo $e->getMessage();
            }
            $statement = "SELECT user, captcha FROM xf_captcha WHERE user=:username";
            //If you have query as a method(Which I don't think so but if you can change "prepare" to your "query"
            $sth = $dbh->prepare($statement);
            $sth->execute(array(":username" => $username));
            $row = $sth->fetch(PDO::FETCH_ASSOC);
    ?>

実行括弧では、配列を使用:usernameして変数のパラメーターを埋めることができます$username

PDO クラスの例を調べることも、PDO とメソッドをよりよく理解するのに役立つと思います (PHP PDO マニュアルも参照できます)。

于 2013-09-26T08:39:44.383 に答える
-1

テーブルが存在しない場合にも発生します。それが実際に存在することを確認し、ハードドライブのエラーが原因でデータベース内の単なるホルダーではないことを確認してください。

その場合、「手動で」読み取ろうとしたときに phpMyAdmin でエラーが発生した場合は、データベース/テーブルを再作成することをお勧めします。

于 2015-06-18T18:49:35.127 に答える