Q:

Is there a PHP security exploit with $_POST in my code?

I posted this question here.
And an answer stated that I should not do:
$table_name = 'survey_'.$_POST['surveyid'];

because

It is easy for a hacker to exploit your site if you include $_GET or $_POST data directly in any SQL string.

Here is the code.  Do you see any security exploits?
if(ctype_digit($_POST['surveyid']) && $_POST['surveyid']>0){

    $table_name = 'survey_'.$_POST['surveyid'];

    $query = 'CREATE TABLE '.$table_name.' (
            `responseid` INT NOT NULL AUTO_INCREMENT,
            `textarea1` TEXT NULL,
            `textarea2` TEXT NULL,
            `textarea3` VARCHAR(255) NULL,
            `drop_down1` VARCHAR(255) NULL,
            `drop_down2` VARCHAR(255) NULL,
            `bool1` BIT NULL,
            `bool2` BIT NULL,
        PRIMARY KEY (`responseid`))';
}

I don't see a vulnerability.... why is $_POST['surveyid'] vulnerable? It is being sanitized by ctype_digit...

A:

Since you validate that $_POST['surveyid'] contains at least one digit and contains only digits, your query is safe.
However, the CREATE TABLE operation that you are trying to do strikes me as a horrible thing to do.  CREATE TABLE is a Data Definition Language operation, and DDL commands should be executed only in special situations.
Basically, if you routinely create a new table to store responses from each survey, your database schema will be an unmaintainable mess.  I strongly recommend that you post your database schema and describe what you are trying to do in a question to http://dba.stackexchange.com to develop a sane schema that does not require new tables to be created routinely.

A:

Usually what you need is a suvery_id attribute and usage of only one table:
CREATE TABLE 'survey_result' (
    `response_id` INT NOT NULL AUTO_INCREMENT,
    `survey_id` INT NOT NULL,
    `textarea1` TEXT NULL,
    `textarea2` TEXT NULL,
    `textarea3` VARCHAR(255) NULL,
    `drop_down1` VARCHAR(255) NULL,
    `drop_down2` VARCHAR(255) NULL,
    `bool1` BIT NULL,
    `bool2` BIT NULL,
PRIMARY KEY (`responseid`))';

I suppose you'll need proper indexes too (based on your queries).
Note that I renamed responseid to response_id since this format is easier to read (especially if the name contains three or more words).
Having indexed column names, like

`textarea1` TEXT NULL,
`textarea2` TEXT NULL,
`textarea3` VARCHAR(255) NULL,

does not suggest flexible database schema. Number of input boxes on surveys are likely to change. Here is another design approach on Stack Overflow: Schema design for when users can define fields, but you can find others, search for survey system database schema or something similar. Knowledge about database normalization also useful.

