"SELECT :parameter FROM .." in PDO [duplicate] - php

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
I'm trying to select a variable column name in my table, but this doesn't seem to work:
$reponse = $bdd->prepare('SELECT :day AS day FROM TABLE WHERE id= :id');
$reponse->execute(array('day' => 'monday', 'id' => '5'));
$day = $reponse->fetch();
Even by setting 'day', to a sure known element in my table (monday), it doesn't work. Same for id.
Does someone know how to fix that?
I have no php error output, only a mysql query error (that doesn't show).
By replacing ':day' by monday, I have an output.

Due to the order in which the SQL is parsed, there's simply no way to use a bound parameter as part of the SQL statement (for example, a column or table name).
Instead, you'll need to build the string with string concatenation. If the value of :day comes from an external source (database, POST parameter, etc), to avoid possible SQL injection attacks you'll want to validate the input to make sure it's a valid column or expression.

Table and Column names cannot be replaced by parameters in PDO. You will need to filter and sanitize the data manually.

Related

Does sanitizing input data prevent sql injection? [duplicate]

This question already has answers here:
How to use prepare() with dynamic column names?
(2 answers)
How can I prevent SQL injection with dynamic tablenames?
(3 answers)
Closed 4 years ago.
Well, table and column names cannot be replaced by parameters in PDO. As a requirement, mentioning static column name is not possible here. So, I use santize. Is it enough to prevent sql injection like bind param method. What can be best method ?
$id = filter_var($_POST['id'], FILTER_SANITIZE_STRING);
$text = filter_var($_POST['text'], FILTER_SANITIZE_STRING);
$column_name = filter_var($_POST['column_name'], FILTER_SANITIZE_STRING);
$result = $con->query("UPDATE menu SET $column_name='$text' WHERE mid=$id") OR die($con->error);
You can sanitise a value for syntax, you cannot sanitise it for meaning. SQL-injection by its definition means that you make the query do something different than was intended. Here you are leaving your query wide open for anyone to substitute column names, which are essential to the query structure. By allowing users to change columns, you don't have control over what columns may get changed in the query, which is by definition a form of SQL injection.
You need a whitelist of column names users are allowed to change. If a user is allowed to change any column (even the primary id…!?), and you don't feel like keeping a list of column names in an array, then you can query your database for the names of columns in the targeted table and use that as whitelist.

MySQL SELECT * FROM table WHERE name LIKE (?) OR owner LIKE (?); [duplicate]

This question already has answers here:
PHP PDO prepared statement -- MySQL LIKE query
(3 answers)
Closed 6 years ago.
As you can see in the title, I have a table that I want to take use of in a website I have.
This is how the MySQL statement looks like now: SELECT * FROM bth_nav WHERE name LIKE (?) OR owner LIKE (?);
On my website I want to either search for name or owner. Right now I can only search for name but not owner. This is why I'm asking for help, I've tried to rewrite the statement but however I do it i can only search for one of them.
Thanks in advance.
The answer will be a little more complicated then you would expect.
I see question marks in your query, this way I can assume you're using prepared statements (which is good!).
Your old statement was using 1 value (for the name), and now you want to use 2.
You have some options for this to work.
The easiest one would be that you bind the value twice, but that's not the nicest way.
A better way would be to name your parameters, like this:
SELECT * FROM bth_nav WHERE name LIKE (:nameOwner) OR owner LIKE (:nameOwner);
Hence that I use the same name for both parameters here. Now you can bind the value to the named parameter with bindValue, and you need do this only once.

Is there a way to use PDO with a dynamic column name in an UPDATE query? [duplicate]

This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 8 years ago.
It's a little relative to the question I asked here
(PDO adds the apostrophe to the mySQL query) but this time column name is a parameter.
Not working PDO example would be like this:
"UPDATE tbl SET :COL1 = NOT :COL1;"
sure solution like this:
"UPDATE tbl SET $COL1 = NOT $COL1;" // works (but it's not PDO)
but why
"UPDATE tbl SET $COL1 = NOT :COL1;" // does not ??
while
"UPDATE tbl SET $COL1 = :VAL_COL1;" // is ok if I first get and negate COL1 value...
In a prepared statement, a parameter is a constant value that will be passed into the query without affecting how the query will be run. This allows the database to "prepare" the query ahead of time and figure out how it will be executed even without knowing the exact values that will be used.
Using this definition, a query like this does not have any parameters, and so the PDO and non-PDO versions of the query will look the same. Your working (first) example is as good as you're going to get. In fact, I'd claim that your first example actually is the PDO version.
To use a non-database example, a prepared statement is very much like a function in a programming language such as PHP. A function accepts parameters and uses their values, but (in normal circumstances) the parameters are not lines of code that will be run. The same code is run regardless of what the parameter values are - the function code itself is not changed by the parameters.
No. You cannot bind table names or column names as parameters. You can only bind values as parameters.
See more here: Can PHP PDO Statements accept the table or column name as parameter?

Getting a Mysql Results without knowing a column name [duplicate]

This question already has answers here:
Get table column names in MySQL?
(19 answers)
Closed 9 years ago.
As I am still learning PHP and MySQL, I would like to know if it is possible to query a table without knowing it's name. Knowing the table I am querying and the column I would like to retrieve, I can write something like
$book_title=$row['book_title'];
Then I can use the resulting variable later in the script. In each case, each book category table will have a column of interest with a different name. I have several tables on which I am running queries. I am able to query any table by using a variable that always evaluates to the correct table name, because all the input from users corresponds to the tables in the database, so the $_POST super global will always carry a correct table name. The problem is for me to have a
$variable=$row['column'];
in cases where I do not know a column name before hand even though I know the table name.
My queries are simple, and look like
query="select * FROM $book_categories WHERE id=$id";
$row = mysqli_fetch_array ($result);
$variable=$row['?'];
The question mark say, I do not know what column to expect, as it's name could be anything from the tables in the database!
Since I have several tables, the query will zero on a table, but the column names in each table varies so I would like to be able to use one query that can give me an entry from such a column.
I hope my question is clear and that I am not asking for the impossible. If it's ambiguous, I care to elucidate (hope so).
I'm not sure what you mean, but it is possible to reference specifc columns by typing index (starting with 0) something like this: $row[0], $row[1] where 0 indicates the first column, and 1 indicates the second column from the returned recordset.
Example:
If you have a select-statement like this:
SELECT title, author FROM books
You could reference these two columns with $row[0], $row[1]
If you try to get the value of $row[2] you will get an unassigned value because there are only two columns (0 and 1) from the recordset.
If you have a select-statement like this:
SELECT * FROM book_categories
and the recordset returns three columns, then you could access these with $row[0], $row[1] and $row[2]. $row[3] does not exist because there are only three columns (0,1 and 2)
Since you are learning maybe we could take some time to explain why this is possible but many people (including myself) would say this is bad -- or at least dangerous
Why you can
Your SQL query is basically a text string you send to the DB server, which decode that string trying to interpret it as SQL in order to execute the query.
Since all you send to the DB server is text string, you could build that string however you want. Such as using string interpolation as you did:
select * FROM $book_categories WHERE id=$id
That way, you could replace any part of your query by the content of a variable. You could even go further:
$query FROM $book_categories WHERE id=$id
Where $query could by SELECT * or DELETE.
And, why not initializing all those variables from a form:
$book_categories = $_POST['book_categories'];
$id = $_POST['id'];
$query = $_POST['query'];
Great, no? Well, no...
Why you shouldn't
The problem here is "could you trust those variables to only contain acceptable values?". That is, what would append if $book_categories somehow resolve to one table you didn't want to (say myTableContainigSecretData)? And what if $id resolve to some specially crafted value like 1; DELETE * FROM myImportantTable;?
In these conditions, your query:
select * FROM $book_categories WHERE id=$id
Will become as received by the DB server:
select * FROM myTableContainigSecretData WHERE id=1; DELETE * FROM myImportantTable;
Probably not what you want.
What I've tried to demonstrate here is called SQL injection. This is a very common bug in web application.
How to prevent that?
The best way to prevent SQL injection is to use prepared statement to replace some placeholders in your query by values properly shielded against SQL injection. There was an example posted a few minutes ago as a response to an other question: https://stackoverflow.com/a/18035404/2363712
The "problem" regarding your initial question is that will replace values not table or columns identifiers.
If you really want to replace table/columns identifiers (or other non-value part of your query) by variables contents, you will have to check yourself the content of each of these variables in order to prevent SQL injection. This is quite feasible. But that's some work...

PHP mysql_query - update using all variables [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can a number used to name a sql column
I am trying to figure out what is wrong with this code
$query = "UPDATE $table SET '$_GET[qty]'=$_GET[newprice] WHERE 'id'='1'";
this is what $query looks like - UPDATE retail_12x18 SET '25'=100 WHERE 'id'='1'
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''25'=100 WHERE 'id'='1'' at line 1
I have put backticks ' every which way and cant get it to go through, always the same error message.
use backtick around your field name:
UPDATE table SET `25` = '{thevalue}', `100` = '{thevalue}', `200` = '{thevalue}' WHERE wherefield = '{wherevalue}'
See here (look for backtick word): http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
It's a bit hard to know for sure, without seeing the table definition, but:
[1] It might be the column types. For instance this bit:
type=" .$_GET['type'];
is trying to set the value of the "type" column without using quotes. It will fail if the "type" column is type like varchar, for example.
[2] You need to use backtics if you're going to have numeric column names
[3] It really must be said that the main thing that's wrong with your code is that you are putting un-escaped $_GET values into your SQL query. Anyone could mount an SQL injection attack by putting SQL into the URL of the page. Very bad practice.
http://en.wikipedia.org/wiki/SQL_injection

Categories