PDO does not insert after quote - php

I am trying to avoid SQL injection in my page.
// Connect to database server and select database
$connection = new PDO("mysql:dbname=tt8888;host=mysql.tt8888.com", "tt8888", "ttnopassword");
// Quote data to prevent SQL injection
$name = $connection->quote($name);
// Insert now
$connection->query("INSERT INTO Contact (name, eeeee, llll, mmmmm, iiiii) VALUES ('$name','$eeeee','$llll','$mmmmm','$iiiii');");
Without quote(), it inserts just fine. And using print $name;, the quote() part seems work fine. Why is there nothing inserted into database after using quote()?

PDO::quote will put single quotes around your values. So you don't need to do that yourself in your SQL.
Though I'd strongly recommend you switch to using prepare() with named parameters.

Do not use PDO::quote. It is much better to use parameterized queries.
$stmt = $connection->prepare("INSERT INTO Contact (name, e, l, m, i) VALUES (?,
?, ?, ?, ?)");
// This will quote all of the values for you
$stmt->execute(array($name, $eeeee, $llll, $mmmm, $iiiii));
You can also use bind methods (bindParam or bindValue) instead of passing the arguments directly to execute. This will allow you to specify the data types if it's necessary, but it seems like these are all supposed to be strings.

Related

SQL Error #1054 caused by single quotes?

I have built one PHP page which sends virtually identical information to two different tables (one is accessible by all users of the site, the other is a user's individual table).
$post = "INSERT INTO `Alpha` (`number`, `field1`, `field2`,
`field3`, `field4`, `field5`, `field6`, `field7`, `field8`, `field9`,
`field10`) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, '0', '0')";
$dbh = new PDO( "mysql:dbname=essay;host=localhost", "root", "password" );
$selectStatement = $dbh->prepare( $post );
$selectStatement->bindValue(1, $name, PDO::PARAM_STR);
$selectStatement->bindValue(2, $id, PDO::PARAM_INT);
$selectStatement->bindValue(3, $head, PDO::PARAM_STR);
$selectStatement->bindValue(4, $text, PDO::PARAM_STR);
$selectStatement->bindValue(5, $topic1, PDO::PARAM_STR);
$selectStatement->bindValue(6, $topic2, PDO::PARAM_STR);
$selectStatement->bindValue(7, $topic3, PDO::PARAM_STR);
$selectStatement->bindValue(8, $date, PDO::PARAM_INT);
$selectStatement->execute();
This is the code for the first table, and it works. The code for the second table is literally copied and pasted from this - the only difference being that the table name is changed (since it is unique to the user it is also now in the prepared statement) and one of the field names is changed (and I've created a new PDO object), but for some reason it won't work.
I put together a string which represents what the SQL query ought to look like, having it echo out each time I make a query, and when I input it manually I'm getting error #1054.
The strange thing is that the error goes away if I alter the query such that all of my string values are wrapped in single quotes. This, of course, is quite confusing because the first query didn't demand single quotes - why then would the second, since they are almost identical? Do I have some kind of weird setting on my SQL table of which I am unaware? If I could make the database accept the query without single quotes that would be ideal.
Regardless, when I append single quotes to both ends of the variables in my prepared statement, the prepared statement seems to be stripping them out, so I'm not sure how to get the single quotes on, but if I could I suppose that solution would suffice.
Table (and column) names can't be provided as parameters in prepared statements, which your description leads me to believe you've done.
See this old SO question
Have you tried PDO::quote? Looks like it handles escaping strings and might help solve those issues that you're facing.

Viewing escaped characters in database mysql?

I am using mysqli prepared statement to insert values into the database. I know that this extension handles characters escaping properly.
I have a file path : images/serveover/Bellini 83.png, what I am expecting to see after insert is the file path with escaped characters in the database, something like images\/serveover\/Bellini 83.png but I only see the image path as is.
How can I make sure that my string has been properly escaped? Is this view standard in phpMyAdmin where It does not show escaped characters or is it just hiding them on view?
Below is my insert prepared statement with params where all the values are being filled properly :
$insertQuery = $conn -> prepare("INSERT INTO images (image_id, image_date_created, image_date_modified, image_title, image_src, category_id, image_status, image_external_file, another_id) VALUES (null, NOW(), CURRENT_TIMESTAMP, ?, ?, ?,'A', ?, ?)");
if($insertQuery )
{
$insertQuery -> bind_param("ssisi", $title, $image, $row["category_id"], $file, $row["id"]);
$insertQuery -> execute();
$insertQuery -> close();
}
As long as you're dealing with strings, the escaping process simply instructs MySQL to ignore the special properties of a character and treat it like a normal character.
Bob\'s special string
Is entered into the database as
Bob's special string
It's important to note that prepared statements don't use escaping at all. Prepared statements send the query in one set and the data in another, so MySQL doesn't need to escape it, since it knows that's the actual value to store.
You can read more about the process in the MySQL manual
https://dev.mysql.com/doc/refman/5.0/en/string-literals.html

Column count doesn't match value count at row 1 (columns and values are equal)

I'm getting the error: Column count doesn't match value count at row 1
I think, normally this error occurs if the count of the columns and the values aren't equal, but in my code they are...(3).
This is my php code:
$tempsongtitel = $_POST['songtitle'];
$tempinterpret = $_POST['interpret'];
$templink = $_POST['link'];
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel, $tempinterpret, $templink')") or die(mysql_error());
You missed some quotes. Should be:
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link) values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
Otherwise, you were trying to insert all three POST values into the first field.
Moreover, the mysql_ extension has been deprecated and is on the way out and is highly discouraged, especially if you are creating new software.
AND I'll presume you are first sanitizing your data? You're not really taking user input and placing it directly into the database, are you? Even if you don't do any data validation, you should escape your data in the query... easiest and most foolproof way to do that is by using parameterized queries.
The root cause is that your values are all in one set of quotes instead of quoted individually. I think this is a pretty common error, and in my experience it is an easy mistake to make, but not immediately obvious when scanning over your code. You can fix it like this (quick fix, still using deprecated mysql, but with post values escaped):
$tempsongtitel = mysql_escape_string($_POST['songtitle']);
$tempinterpret = mysql_escape_string($_POST['interpret']);
$templink = mysql_escape_string($_POST['link']);
$query = mysql_query("insert into tMusic (Songtitel, Interpret, Link)
values ('$tempsongtitel', '$tempinterpret', '$templink')") or die(mysql_error());
If you can, it would be much better to update your code to use PDO. You could use a prepared statement like this:
$stmt = $pdo->prepare("INSERT INTO tMusic (Songtitel, Interpret, Link) VALUES (?, ?, ?)");
$stmt->bindValue(1, $tempsongtitel);
$stmt->bindValue(2, $tempinterpret);
$stmt->bindValue(3, $templink);
$stmt->execute();
Among the many benefits of using this database extension rather than the old mysql functions it should not be possible to make an error like this in your code. In the prepared statement, there are no quotes around the parameter markers, so if you have VALUES ('?, ?, ?'), or even VALUES ('?', '?', '?') You would get bind errors when trying to bind the values, and the problem would become apparent pretty quickly.
I've found that, even though it's not 100% necessary and it's more time consuming, properly quoting and backticking EVERYTHING helps prevent this from happening.
$myQuery = "INSERT INTO `tMusic` (
`Songtitel`,
`Interpret`,
`Link`
) VALUES (
'$tempsongtitel',
'$tempinterpret',
'$templink'
);";
$runQuery = mysqi_query($DBi, $myQuery) or die(mysqli_error($DBi));
The formatting you use is up to you but this helps me make sure I have a one to one relationship and that I've quoted everything.
Of course that's using mysqli_* in place of the deprecated mysql_* functions AND that's assuming you've set $tempsongtitel, $tempinterpret and $templink properly.

Do I need to escape my data values when I pass them to prepared SQL statements?

When I use prepared statements do I have to use functions like mysqli_real_escape_string or are the executed automatically?
For example should I just use this
$stmt = $mysqli->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam('sd', $name, $value);
or do I have to use something like this
$stmt = $mysqli->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam('sd', mysqli_real_escape_string($name), mysqli_real_escape_string($value));
Which functions are recommended to avoid sql injections?
No, you do not need to escape your parameters. In fact, escaping variables that you then pass in to a parametrized query is an error and will give you incorrect results.
When using parameterized queries, the escaping is done by the API. your first method is correct.
If you are doing raw text queries, then you should escape your parameter values.
Prepared statements automatically scrub what you're inserting. When you do the following:
$stmt = $mysqli->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
That bindParam function is doing all the necessary cleaning for you and then inserting that value into the query string.
Fun fact, prepared statements are a hack built on top of a hack in their fundamental idea :)

how to escape input but save unescaped into the database

It is said that in order to prevent from SQL injection one should filter the input data eg. with addslashes or mysql_real_escape_string depending on used connection modules
However, data escaped with addslashes is being saved into the database WITH the slashes, so a user surname would save as O\'Reilly instead O'Reilly. The one needs to use stripslashes to display it correctly.
So how do I use addslashes and save into the database without slashes? Is it actually the way it should be done?
You DONT use addslashes you use the appropriate DB specific escaping function like mysql_real_escape_string.
if you are using PDO then using a prepared statement will escape the variables as part of binding process. In this case all you need to do is something like:
$pdo = new PDO($dsn, $user, $name);
$stmt = $pdo->prepare('INSERT INTO your_table (col1, col2,col3) VALUES (?, ?, ?)');
$stmt->execute(array('value 1', 'value 2', 'value 3');
OR for extra readability and esier reuse you can use named params:
$pdo = new PDO($dsn, $user, $name);
$stmt = $pdo->prepare('INSERT INTO your_table (col1, col2,col3) VALUES (:col1, :col2, :col3)');
$stmt->execute(array(':col1' =>'value 1', ':col2' =>'value 2', ':col3' =>'value 3');
addslashes is supposed to be a one-size-fits-all escaping mechanism. If you MySQL-escape an addslash-escaped strings, of course the value including the addslash slashes will be saved to the database. Use either or, not both.
Having said that, don't use addslashes. It serves no real purpose. Use the specific escaping mechanism for the appropriate situation. I.e., only use mysql_real_escape_string. Or prepared statements, which avoids the whole escaping mess to begin with.
If you use prepared statements (via PDO or the mysqli library, for instance,) you don't need to escape or filter anything.

Categories