quotes are inserting by PDO - pdo

im using PDO for my insert query like below:
$stmt=$con->prepare("INSERT INTO `user`(`name`) VALUES (:name)");
$stmt->execute(array(":name"=>$_POST['name']));
but when user input includes quotes or double quotes and etc,those bad parameters are still inserting in my database!
where is my mistake?

PDO prepare() statement is not for preventing the attacker from inserting bad queries.
This function hast just made it easy to realise what type of data is being inserted in query.
There has a lot of way to make this function fool
It will be the good try (practice) to validate and sanitize the data before participating in query

Related

Syntax error in INSERT INTO statement

I am trying to insert some information in an MS Access database.
In my database I have the following columns and types:
log_order - Autonumber (I need this to keep the order where inserted in the db),
userID - Text,
time - Text,
date_ - text,
message - Text.
My query:
command.CommandText = "INSERT INTO logs(userID, time, date_, message) VALUES ('"+verifiedUser+"', '"+msg_time+"', '"+msg_date+"', '"+msg+"')";
OleDbDataReader reader = command.ExecuteReader();
The error that I get:
System.Data.OleDb.OleDbException: 'Syntax error in INSERT INTO statement.'
I tried several posts but no post helped me. I believe there might be a problem with the autonumber column (log_order). Because of what I remember I don't have to include it in the query.
PS: I know I have to pass the values as parameters.
Thank you in advance
Probably one of your variables (msg?) contains an apostrophe
The way you've written your SQL is a massive security risk. Please immediately look up "parameterized queries" and never, ever, ever write an sql like this again (where you use string concatenation to tack the values into the query). Your code has a proliferation of issues and using parameterized queries will solve all of them; they aren't difficult to write
It seems your data in some of the variables passed in INSERT may be causing this error. Try debugging the value in command.CommandText before executing it.
If any of the variables have a single quote they must be escaped...
Ref: How do I escape a single quote in SQL Server?
Also brush up on SQL Injection Ref: SQL Injection
I totally agree with all that has been said, but to answer your question directly, I am pretty sure you will need to put square brackets around your field names. OleDb tends not to like special characters and could well be having a problem for example with date_ ; sending [date_] instead should get round the issue.
It will not like time either. Same solution
Addendum on SQL Injection
As an aside, in fact calling Access through OleDb is relatively protected from SQL Injection. This is because any attempt to execute multiple instructions in one command fails. (You get an incorrect formatted string error). So whilst you could argue that what you are doing is safe, it is not for other db providers. The sooner you get into good habits, the less likely you will be to introduce a vulnerability in a case where it could be dangerous. If it seems like you are getting a stream of abuse, it is just because everyone here wants to keep the net safe.

How PDO prepared statements help to prevent SQL vulnerable statements?

I'm so confused or rather I'm like, soooooooooo confused with pdo prepared statements. I know that prepared statements are the best way to keep data safe from hackers.
From : How can prepared statements protect from SQL injection attacks?
We are sending program to the server first
$db->prepare("SELECT * FROM users where id=?"); where the data is
substituted by some variable called "placeholder".
Note that the very same query being sent to the server, without any
data in it! And then we're sending the data with the second request,
totally separated from the query itself:
$db->execute($data);
query-
$query=$db->prepare("SELECT * FROM USERS WHERE username=?");
$query->execute(array($tex));
$tex=blah; DROP TABLE users;--
then it will be like - SELECT * FROM USERS WHERE username=blah; DROP TABLE users;--
how prepare statements will help me with this example above?
I'm really sorry if this question is vague to understand. Any help would be appreciated. Thanks in advance.
The prepared statement handler will make sure the bound value is always used as valid SQL value/literal (ie. an SQL string or a number) and never as 'raw SQL text'1.
This is why placeholders values cannot be used as identifiers such as column or table names or act as other SQL keywords; and cannot generate the vulnerable query hypothesized. Instead it is treated as the following:
WHERE username='blah; DROP TABLE users;--'
--^ placeholder ensures valid SQL string value is used
-- (note automatic/implicit addition of SQL quotes)
And even when binding with 'more tricky' data:
$tex = "blah'; DROP TABLE users;--"; // embedded SQL quote character
It would still be safe:
WHERE username='blah''; DROP TABLE users;--'
--^ placeholder STILL ensures valid SQL string value is used
Thus, when using placeholders, it is impossible to generate the SQL that is vulnerable (in this way).
For SQL Injection the 'shape' of the query (which includes keywords and identifiers, but excludes values) must itself be altered by the input.
1 Technically placeholders values can also be sent through a separate data channel (depending on adapter/driver) and thus might not even appear in the raw SQL query itself.
However a simple way to think about why placeholders are safe, or how they 'work' is:
When using placeholders the adapter ensures that the equivalent of 'sql really safe escape' and applicable quoting is always used for every bound text value - and is thus impossible for accidentally forget.

VBA ADODB multirow insert not working

I am trying to figure out how to do multirow inserts using ADODB in VBA excel.
My problem seems to be that i can`t figure out the correct syntax to use for this simple task, even after searching I am still lost as to why it does not work.
I have no problem doing a single insert using the statement
INSERT INTO test.dbf ('field1','field3') VALUES ('test1','test11')
But as soon as I try
INSERT INTO test.dbf ('field1','field3') VALUES ('test1','test11'), ('test2','test22')
It gives me the following error
[Microsoft][ODBC dBase Driver] Missing semicolon (;) at end of SQL statement.
I of course tried adding the semicolon at the end of the statement and it was no help at all, I also tried running the statement with out specifying the columns, all to no avail.
Any suggestions as to what I am doing wrong? I would like to avoid doing 8,000 individual inserts.
Thanks in advance
The SQL syntax for multi-row inserts is newer than the ADODB/ODBC interfaces and so their SQL parsers do not recognize it. Consequently your choices are:
Use VBA to specify this as a pass-thru query. This should work so long as the DBMS you are executing in recognizes the new insert syntax. However, this has the significant downside that you are almost certainly exposing your database to injection if your insert content is based on user input. (Note: this has nothing to do with pass-thru, but rather with the fact that you are using string composition to do your inserts, rather than using the ADODB table objects).
Just use the VBA/ADODB table objects to insert multiple rows. This does not use the newer multi-row insert SQL syntax under-the-hood, but still works fine. The only reason to try to leverage the multi-row syntax is if you have a performance problem, and there are many other performance options available.

Moving from Access backend to SQL Server as be. Efficiency help needed

I am working on developing an application for my company. From the beginning we were planning on having a split DB with an access front end, and storing the back end data on our shared server. However, after doing some research we realized that storing the data in a back end access DB on a shared drive isn’t the best idea for many reasons (vpn is so slow to shared drive from remote offices, access might not be the best with millions of records, etc.). Anyways, we decided to still use the access front end, but host the data on our SQL server.
I have a couple questions about storing data on our SQL server. Right now when I insert a record I do it with something like this:
Private Sub addButton_Click()
Dim rsToRun As DAO.Recordset
Set rsToRun = CurrentDb.OpenRecordset("SELECT * FROM ToRun")
rsToRun.AddNew
rsToRun("MemNum").Value = memNumTextEntry.Value
rsToRun.Update
memNumTextEntry.Value = Null
End Sub
It seems like it is inefficient to have to use a sql statement like SELECT * FROM ToRun and then make a recordset, add to the recordset, and update it. If there are millions of records in ToRun will this take forever to run? Would it be more efficient just to use an insert statement? If so, how do you do it? Our program is still young in development so we can easily make pretty substantial changes. Nobody on my team is an access or SQL expert so any help is really appreciated.
If you're working with SQL Server, use ADO. It handles server access much better than DAO.
If you are inserting data into a SQL Server table, an INSERT statement can have (in SQL 2008) up to 1000 comma-separated VALUES groups. You therefore need only one INSERT for each 1000 records. You can just append additional inserts after the first, and do your entire data transfer through one string:
INSERT INTO ToRun (MemNum) VALUES ('abc'),('def'),...,('xyz');
INSERT INTO ToRun (MemNum) VALUES ('abcd'),('efgh'),...,('wxyz');
...
You can assemble this in a string, then use an ADO Connection.Execute to do the work. It is frequently faster than multiple DAO or ADO .AddNew/.Update pairs. You just need to remember to requery your recordset afterwards if you need it to be populated with your newly-inserted data.
There are actually two questions in your post:
Will OpenRecordset("SELECT * FROM ToRun") immediately load all recordsets?
No. By default, DAO's OpenRecordset opens a server-side cursor, so the data is not retrieved until you actually start to move around the recordset. Still, it's bad practice to select lots of rows if you don't need to. This leads to the next question:
How should I add records in an attached SQL Server database?
There are a few ways to do that (in order of preference):
Use an INSERT statment. That's the most elegant and direct solution: You want to insert something, so you execute INSERT, not SELECT and AddNew. As Monty Wild explained in his answer, ADO is prefered. In particular, ADO allows you to use parameterized commands, which means that you don't have to put-into-quotes-and-escape your strings and correctly format your dates, which is not so easy to do right.
(DAO also allows you to execute INSERT statements (via CurrentDb.Execute), but it does not allow you to use parameters.)
That said, ADO also supports the AddNew syntax familiar to you. This is a bit less elegant but requires less changes to your existing code.
And, finally, your old DAO code will still work. As always: If you think you have a performance problem, measure if you really have one. Clean code is great, but refactoring has a cost and it makes sense to optimize those places first where it really matters. Test, measure... then optimize.
It seems like it is inefficient to have to use a sql statement like SELECT * FROM ToRun and then make a recordset, add to the recordset, and update it. If there are millions of records in ToRun will this take forever to run?
Yes, you do need to load something from the table in order to get your Recordset, but you don't have to load any actual data.
Just add a WHERE clause to the query that doesn't return anything, like this:
Set rsToRun = CurrentDb.OpenRecordset("SELECT * FROM ToRun WHERE 1=0")
Both INSERT statements and Recordsets have their pros and cons.
With INSERTs, you can insert many records with relatively little code, as shown in Monty Wild's answer.
On the other hand, INSERTs in the basic form shown there are prone to SQL Injection and you need to take care of "illegal" characters like ' inside your values, ideally by using parameters.
With a Recordset, you obviously need to type more code to insert a record, as shown in your question.
But in exchange, a Recordset does some of the work for you:
For example, in the line rsToRun("MemNum").Value = memNumTextEntry.Value you don't have to care about:
characters like ' in the input, which would break an INSERT query unless you use parameters
SQL Injection
getting the date format right when inserting date/time values

Encoding string in order to Insert SQLite

I'm using sqlite3_exec() function in order to execute an SQL Insert command. The problem starts when I need to insert strings that need to be encoded.
For example, I want to insert the following string: "f('hello')". If I want to insert this string I need to change "'" to "''".
My question is, how do I encode these strings? Is there a function I can count on? or a table that details all the needed encodes?
Thanks! :-)
Instead of manually escaping strings (which is error-prone and invites SQL injection attacks), I'd strongly recommend using prepared statements and bind values; read up on sqlite3_bind_XXX and sqlite3_prepare_v2
Using bind values will solve this problem and it will also make sqlite faster because it remembers previously executed sql statements and it can reuse their execution plans. This doesn't work when the sql statement is always slightly different because it hashes the complete sql statement.
sqlite_mprintf supports %q for that.
"Maybe" you should use something like a prepared statement. I am not an expert in SQLite, but I found this link (http://www.sqlite.org/c3ref/stmt.html) and it could help you. It is about SQL Statement Object.