1

これまでのところ、次のコードがあり、ページに渡された$_GET用語に基づいて2つのクエリを実行します。

クエリ1)$ _GET->Worksから渡されたテーブル名に基づいて列名を取得します。

クエリ2)そのテーブルからデータを取得します->機能しません。

2番目のクエリは次のとおりです。

$table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));

クエリを次のように変更すると:

$table_data = db_adminQuery('SELECT * FROM events', array());

動作しますが、そもそもなぜ動作しないのか理解できません。私が何かを逃したか、いくつかのばかげたエラーがある場合、私はこれの何が悪いのかわからないので私に知らせてください。

完全なソースは次のとおりです。

    if(isset($_GET['page']))
    {
        $pages = array('events','news','ads','slider');
        $page = trim($_GET['page']);

        if(in_array($page, $pages))
        {
            include 'db.php';
            administer($page);
        }

    }


    function administer($p)
    {

        /*
        *
        *   TABLE COLUMN NAMES & TYPES
        *
        */

        $columns_tmp = db_adminQuery('SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = \'evented\' AND TABLE_Name = :table_name', array(':table_name' => $p));

        if(!empty($columns_tmp))
        {
            $columns = array();
            foreach ($columns_tmp as $key => $value) 
            {   
                array_push($columns, array('name' => $value['COLUMN_NAME'], 'type' => $value['DATA_TYPE']));
            }
        }

        /*
        *
        *   TABLE DATA
        *
        */

        $table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));
        print_r($table_data);

        $table = '<table cellpadding="0" cellspacing ="0">'.PHP_EOL;
        $table .= '<tr>'.PHP_EOL;

        foreach ($columns as $key => $value) 
        {   
            $table .= '<th style="padding:5px;">'.$value['name'].'</th>';
        }

        $table .= '</tr>'.PHP_EOL;

        foreach ($table_data as $data_key => $data_value) 
        {
            $table .= '<tr>'.PHP_EOL;
            //$table .= '<td>'.$data_value.'</td>';
            $table .= '</tr>'.PHP_EOL;
        }

        $table .= '</table>';


        echo $table;    
    }


    function db_adminQuery($query, $params = array(), $return = true)
    {
        global $db;

        if($stmt = $db->prepare($query))
        {
            // PARAMETERS
            if(!empty($params))
            {
                foreach($params as $key => $value) 
                {
                    $stmt->bindParam($key, $value); 
                    echo $key.' - '.$value.'<br>';      
                }
            }

            $stmt->execute();

            if($return == true)
            {
                $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

                return $result;
            }
        }
        return false;
    }
4

1 に答える 1

1

SQLでは、クエリをprepare()する前に、すべてのテーブル名とすべての列名およびその他のSQL構文を修正する必要があります。そうしないと、解析では、名前を付けたテーブルが実際に存在することを検証できず、そのテーブルを操作するのに十分な権限があるなどです。また、クエリオプティマイザは、その時点で使用するインデックスを決定する場合があります(MySQLの場合は信じていますが、オプティマイザはexecute()時間までそれを行いません)。

したがって、テーブル名、列名、式、SQLキーワードなどをパラメーター化することはできません。

クエリパラメータは、引用符で囲まれた文字列リテラル、引用符で囲まれた日付リテラル、数値定数など、通常は定数値を使用する場所でのみ使用してください。

テーブル名をSQL文字列に安全に補間するには、補間する前に値をホワイトリストに登録してください。つまり、テーブル名の入力を、コードにある既知のテーブルのリストと照合します。ハードコーディングするか、構成ファイルに入れるか、データベースインスタンスにクエリを実行して、存在するテーブルを検出します。

ユーザーが存在することがわかっているものと一致しない文字列を入力した場合は、間違いを犯した可能性があります。そうでない場合は、SQLインジェクションを実行しようとしています。いずれにせよ、それらの入力を使用しないでください。デフォルトのテーブル名を使用するか、エラーを出して再試行させてください。

于 2013-03-07T23:21:27.317 に答える