Using the Go SQL library we can create SELECT, INSERT, UPDATE and DELETE statements with parameters like this:
db.Query("SELECT * FROM database.table WHERE param = ?", param_value)
I want to create tables from user provided input that describes the table structure, users will be asked for the name of the table and the name and type of each column they want to create. However, building a CREATE statement in the query interface Creating a CREATE statement by concatenating strings together works, but that's a SQL injection attack waiting to happen.
Is there a way to parameterize CREATE statements using the Go SQL library?
SQL query parameters take the place of a scalar value only.
That is, you can use a parameter to substitute only where you would otherwise use a constant quoted string, constant quoted date/time, or constant numeric.
SQL query parameters can't be used for:
Table names, column names, or other identifiers
SQL expressions
Lists of scalar values (like in an IN(...) predicate)
SQL keywords
The proper way to write your app that takes user input which describes table structure is to interpret the user input as a guide, not as literal SQL syntax. Avoid passing user input (or any unsafe content) through to be executed as part of any SQL statement.
Related
Is there any known danger with exposing the use of a FullText index to internal and possibly public users?
Assuming the queries are properly parameterized, is there any way that a user could abuse the inputs to trigger a SQL injection or denial of service attack?
// SQL Server
select * from content_table WHERE CONTAINS((Title, Subtitle, Body), #fullTextSearch);
// MySQL
select * from content_table WHERE MATCH(Title, Subtitle, Body) AGAINST (#fullTextSearch);
// Oracle
select * from content_table WHERE CONTAINS(Body, #fullTextSearch);
The trigger for this question is the large variety of inputs a user could specify and the fact that the different SQL servers have different query syntax and at least some (MySQL) will return a syntax error if an invalid query is specified.
'FORMSOF(INFLECTIONAL, model NEAR airplane)'
'NEAR((term1, term2),5) AND term3'
'NEAR((term1, term2),5) OR NEAR((term3, term4),2, TRUE)'
'+join +(>left <right)'
'electric INPATH (/purchaseOrder/items/item/comment)'
When talking about SQL injection the risk is that someone can introduce SQL keywords into the query itself by adding SQL to a data parameter.
This is why separation of data and query is absolutely critical. This normally plays out by using placeholder values, as in:
SELECT * FROM content_table WHERE MATCH(Title, Subtitle, Body) AGAINST (?);
In the case of search there's often two levels you need to be aware of:
The SQL layer where you're using raw SQL keywords to express the query conditions, such as WHERE x=? AND y=?
The search layer where you're expressing conditions within a string, like WHERE CONTAINS(?) which has a bound data parameter '"computer software" NEAR hardware)'
Note that the second form has a syntax within a string, so if you're exposing that you're not at risk of SQL injection per-se, but you may end up receiving a lot of syntax errors caused by bad user input that you need to handle.
In the first case if you need to compose the query conditions you need to follow the usual rules:
Do not permit:
Inclusion of unknown fields into the query.
Inclusion of unknown operators into the query.
Maintain as strict a separation between query and data as is practical.
You may need to parse the request's data into components that can be recomposed into a SQL query. This can get messy, especially if you're allowing a lot of latitude in how things can be searched, so try and keep it as simple and testable as possible.
If you have unit tests, include one that's deliberately hostile and tries to introduce invalid or injection-type data into the query. Ensure the data is properly contained.
Note: If you're calling a stored procedure using placeholder values, but the stored procedure composes SQL statements using concatenation you're still at risk, so you need to be absolutely certain you're keeping the data separated from the query. If you have a query with zero user data introduced in it there is no risk of SQL injection.
I am currently in the process of moving all my Access databases to a MySQL server. I have some pretty big queries I would like to convert into sql direct.
The only thing is that in those queries I am using the content of a textbox in my form :
IIf(IsNull([Formulaires]![DialogueMAJDossier]![FiltreTypeEntree]),[TypeDossier],[Formulaires]![DialogueMAJDossier]![FiltreTypeEntree])
(Excuse me for all the names being in french)
I know that when I convert it to MySQL syntax, it should give something like this :
IFNULL(`Formulaires`.`DialogueMAJDossier`.`FiltreTypeEntree`, `TypeDossier`)
But I have no idea how to account for the text box value in my query.
Any help will be gladly appreciated
Pass-Through queries cannot have parameters, so you'll have to use a workaround.
Option 1:
Save the SQL with "variables" in a template table, e.g. SELECT foo, {FiltreTypeEntree} FROM bar.
Then before executing the Pass-Through query, read the template SQL, Replace() the variable with the result of your IIf expression, and set the .SQL property of the query with the final string.
Option 2:
Create a "Variables" table in MySql. Fill its fields via code, and have your Pass-Through query join this table to get the variable values.
In a multi-user scenario, you'd have to introduce some kind of session management for Option 2, so I'd go with (1) in this case.
I have found the following option screen when creating a Stored Procedure in phpMyAdmin.
Now I wonder what everything means.
I know the Routine name, Type, Parameters, Definition, Definer, Security type and Comment options.
I however do not know what to do with Is deterministic and SQL data access. I have tried to Google it, but couldn't find it. Can someone enlighten me what those values mean?
IS DETERMINISTIC:
A procedure or function is considered “deterministic” if it always produces the same result for the same input parameters, and “not deterministic” otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC is given in the routine definition, the default is NOT DETERMINISTIC.
SQL DATA ACCESS:
CONTAINS SQL indicates that the routine does not contain statements that read or write data. This is the default if none of these characteristics is given explicitly. Examples of such statements are SET #x = 1 or DO RELEASE_LOCK('abc'), which execute but neither read nor write data.
NO SQL indicates that the routine contains no SQL statements.
READS SQL DATA indicates that the routine contains statements that read data (for example, SELECT), but not statements that write data.
MODIFIES SQL DATA indicates that the routine contains statements that may write data (for example, INSERT or DELETE).
I'm using SSRS with MySQL and need to handle the multi-select parameters from SSRS going into my routines (stored procedures) in MySQL.
SSRS passes a multi-select parameter as a comma separated string:
"1,2,3,4"
The common way this is done in SQL Server is by using a table-valued function that would return a table with a row for each value. You then join to this table and all is well.
What is the best way to handle this situation in MySQL, due to the fact that it does not have an equivalent table valued function?
I have seen suggestions to use a temp table in a function, however I will have multiple simultaneous calls of this so that will most likely not work.
My table contains the following fields, Name,Age,Salary,Phone,DOB. Based on a settings table, I have to select only some fields. For example, I say in settings, only Name and Phone is required. How can I do it using stored procedure ?
EDIT :
Which one is good.
Select the required fields from the table.
Select all columns and in ASP.NET page, use .Visibility property to hide or show columns
SQL is a fixed column language: columns can not be added or removed "on the fly"
You would need to use dynamic SQL to build a SELECT statement, or use IF statements to execute different ones. However, you open up caching, security and injection issues.
Personally, I'd ignore columns in the client code and have a simple, single efficient SQL query. The contract or API between SQL Server and the client should be static and predictable. If the settings table is applied in SQL Server, your client doesn't know what columns to expect. If your client does know, then it can ignore them.
After your edit, option 2, kind of.
But the data should be removed before being rendered in the page.
Keep it simple: don't try to optimise anything yet
You would need to have multiple different selects - based on your settings table - in your stored proc to return the different sets of data.
CREATE PROCEDURE dbo.YourProcedure(...)
AS BEGIN
DECLARE #Setting INT -- ?? whatever it is
SELECT #Setting = Choice FROM dbo.YourSettingsTable WHERE ....... ???
IF #Setting = 1
SELECT Name, Phone
FROM dbo.YourDataTable
ELSE
SELECT Name, Age, DOB, Phone, Salary
FROM dbo.YourDataTable
END
Using this approach, however, has its dangers - since the stored proc might return one set of data or quite another, your SQL Server query optimizer might make a very good decision on how to access the data for one setting - but when your setting changes, that execution plan will be totally outdated, thus potentially leading to horrible performance......
On the other hand - it might be easier to determine that setting before calling your stored proc - and then just pass in that setting as a stored proc parameter.
Or even better yet: have separate stored procs for each "scenario" - and then from the caller, call the appropriate stored proc depending on the value of your setting....
Create the sql you want dynamically then execute it with exec.
declare #sql varchar(500)
set #sql = 'select 123'
exec (#sql)
The above code should help you understand what you need to know.
Have a stored procedure for each set of fields you want to select
Allow the list of field names to be passed in as a parameter