I know the right way to sanitize sql strings in Perl is to use a prepared statement, however, this particular Perl script is generating statements to be executed later in a different environment, not Perl. It has no database to connect to.
How can I safely escape a string for insertion into a MySQL query. The solution doesn't have to be portable.
Unfortunately the quoting function used by DBD::mysql, and the MySQL client library in general, requires an active database handle. According to the documentation, "this is needed because the escaping depends on the character set in use by the server".
I can think of a few hacky solutions, but none of them are really satisfying, so let's work with this from the docs:
Characters encoded are “\”, “'”, “"”, NUL (ASCII 0), “\n”, “\r”, and Control+Z. Strictly speaking, MySQL requires only that backslash and the quote character used to quote the string in the query be escaped.
This suggests that you can probably get away with a quoting function that does either
s/([\\"'])/\\$1/g;
or
s/([\\"'\0\n\r\cZ])/\\$1/g;
although I would still be wary.
You could just check for special chars in the variables you add to your query string that are required to do an SQL-Injection such as ";" or brackets and replace them or throw them out?!?
Related
I'm running a SQL query using RUNSQL into a CL program. This query is a basic SELECT statement and uses the exclamation mark to concatenate strings.
For years until yesterday, it worked fine. Now, out of nowhere, I've got a SQL0104 message displaying Token '!' not valid every time I run the program.
If I run the query manually using STRSQL, it works.
Did this occur to someone ?
Best regards.
DB2's operator for string concatenation is actually the double pipe ||.
The documentation says:
Use the concatenation operator (||) to join two values of an expression into a single string. In some non-English, single-byte character sets, the || can display as !! (exclamation marks) or other special characters.
So your issue may be caused by a change in the character set of your client. Just use the standard operator, and your code will work regardless.
Sometimes it works anyway if I forget the ;. But sometimes it doesn't.
And in JDBC and Android SQLite, it seems that I don't need ; at all. I am confused.
When should I use a semicolon?
semicolon indicates end of a statement, so if there are multiple statements then you should use semicolon else it will work fine.
I generally use semicolon as a practice, it can be useful even when you are running queries on sql client e.g. in Sql Developer using semicolon is very helpful if you have multiple statements on worksheet, as you can simply go to that particular statement and use F9 to execute that, without semicolon this is not possible.
It is not mandatory if you run a single query at time, it comes necessary instead if you want to run multiple query with a single command.
However in most of JDBC drivers out there it is not possible to add multiple query separated with semicolon in a single JDBC Command, it exist however the addBatch method that allow you to add multiple statements :
java.sql.Statement stmt=con.createStatement();
stmt.addBatch(insert_query1); //insert_query1
stmt.addBatch(insert_query2); //insert_query2
As a rule of thumb, in JDBC semicolon is not necessary at all, if you need multiple statement use addBatch.
Usually the semicolon is not part of the actual syntax of a statement (as most database internal APIs execute a single statement at a time). Instead the semicolon is an 'end-of-statement' marker or statement separator that is - usually - defined in CLI or scripting tools for the database. This allows that tool to know when a statement ends, so it can send that single statement to the database for execution.
On the other hand, the JDBC API is intended to execute a single(!) statement at a time, therefore you don't need such a separator (the statement is the whole string). This means that a semicolon is not needed, and as it is not part of the actual statement syntax for a lot of database it is also a syntax error to include it. Some JDBC drivers will strip the last ; from a statement to 'fix' that, some drivers don't.
Some drivers allow - contrary to the JDBC specification - multiple statements to be executed as a single string, this usually has to be enabled with a connection property, for example for MySQL it is the option allowMultiQueries (see the MySQL properties for details).
Depends on the DBMS and version number. Semicolons are often optional at the end of a single statement. But if you are going to execute a script with more than one statement, they need to be terminated by a semicolon.
Except maybe the last one. But it seems bad form to be inconsistent.
Hi there I'm using JPA to query a database and I should do a column like 'whatever%' query.
My DB is currently Mysql so I could do that without problem, but I was wondering if there was somewhere a method to retrieve the Wildcard character of the database.
There's little chance I change the DB but well ... I'm trying to be as generic as possible.
So is "%" the only wildcard (not talking about _) used, and will forever be ?
Thanks for info!
% is ANSI SQL. This value isn't configurable in any of the major databases, and as such there is no need for these databases to provide a method to return the wildcard character.
This should only be a concern if you think you might migrate to a non-ANSI SQL database, such as MS Access, which uses a * as a wildcard character.
If is is a possibility, I'd suggest making the wildcard character configurable in your application, and provide a variable containing the wildcard character instead of a hard-coded character.
I am doing some research in web security, and the reviser of my article said:
"It should be clear that to avoid SQL Injection, the application should use prepared statements, stored procedures and escape input"
My question is: Is one of these methods isn't enough? Ok, prepared statements or stored procedures are better than a simple escape, but if I use PDO, why i should escape the input or have a stored procedure? Does this make sense?
I would change the reviser's wording to:
It should be clear that to avoid SQL Injection, the application should use prepared statements, escape input, or filter application data before interpolating into an SQL string.
It's not necessary to escape a value if you're going to pass as a parameter. In fact, you should not, because you'll insert literal backslashes into your data.
You need to interpolate strings into your SQL statement when you can't use a query parameter. Examples include:
Table names and column names, which have their own syntax for delimited identifiers. These must be part of the SQL query at prepare time, so the RDBMS can parse and validate them.
SQL keywords, which should be sanitized but cannot be escaped because they are not delimited.
Other syntax or expressions.
Some cases where literal values must be provided at prepare time, e.g. MySQL's fulltext functions do not support parameters for the search pattern.
Stored procedures are not a defense against SQL injection. You can prepare and execute unsafe dynamic SQL statements inside a stored procedure. See http://thedailywtf.com/Articles/For-the-Ease-of-Maintenance.aspx for a great story about that.
I cover all these cases in my presentation SQL Injection Myths and Fallacies. That may be a helpful resource for you.
I also cover SQL injection defense in a chapter of my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
If i use PDO, why i should [es]scape the input or have a stored procedure?
As long as you always use PDO, I don't see a reason to bother with input escaping or SPs.
When in doubt, ask yourself: will this piece of plain input data be escaped by some API down the line? Most of the time they will, except when you manually build SQL sentences from input data.
You should not escape if you use PDO. You should not escape if you use JDBC Prepared Statements with parameters. Similarly, most other APIs also take care of this. Stored procedures are not even concerned with escaped data and using them will not magically avoid SQL injection security issues if the input data is not escaped in the SQL that runs the procedure.
Always SQL-Escape data that you put in SQL sentences. Never SQL-Escape data outside SQL sentences.
I am forced to use a dumb-as-nails Windows program (called IDCentre, made by Datacard, if you have the deep misfortune to use it) that says it can deal with ODBC databases.
So, I hooked it up to my MySQL database. All is well so far.
Then I noticed that it barfs when it attempts to do an update. The SQL that MySQL deems bad contains "[" and "]" as quote characters, which, of course, is what Microsoft SQL Server and Access both use.
I don't think there's a way in this awful program to change how it quotes SQL. Can I go the other way? Is there a way to make MySQL use "[" and "]" as quote characters?
http://dev.mysql.com/doc/refman/5.1/en/load-data.html
LOAD DATA INFILE. Specify the field encloser.
Thanks for all the input; I genuinely appreciate it.
I didn't have control over the IDCentre program, but I did wrangle control of the particular table it's writing to, and changed the table identifiers so that quotes of any kind aren't required. I was hoping and praying that maybe IDCentre would be smart enough to realize it didn't need quotes, and so hence wouldn't send brackets. Indeed that's what happened.