What does the code following CREATE FUNCTION being a string imply? - sql

From a great reply:
in PostgreSQL, CREATE FUNCTION is indeed a "SQL statement" but is is merely a
"wrapper" to specify a block of code that is executed by something
different than the SQL query "engine". Postgres (unlike other DBMS)
supports multiple "runtime engines" that can execute the block of code
that was passed to the "CREATE FUNCTION" statement - one artifact of
that is that the code is actually a string so CREATE FUNCTION only
sees a string, nothing else.
What are the consequences of "the code is actually a string so CREATE FUNCTION only sees a string, nothing else"?
Is that considered as dynamic SQL? Does it prevent or introduce SQL injection risk, compared to dynamic SQL?
How is that different from other RDBMS (if any?) where "the code is not a string"?
Thanks.

PostgreSQL is highly extensible, and you can for example define your own procedural language to write functions in.
PostgreSQL knows nothing about the language except that it has to call a certain language handler to execute the function.
The way that was chosen to implement this is to simplify pass the code as a string.
This is just an implementation detail and does not make PostgreSQL functions any more or less vulnerable to SQL injection than other RDBMS.
There are several levels on which you have to defend yourself against injection:
The function arguments: Here you should choose non-string data types whenever possible.
The SQL statements within the function: Here you should avoid dynamic SQL whenever possible, and if you have to use dynamic SQL, you should insert variables using the %L pattern of the format function.
Again, this is the same if function bodies are specified as strings or not.

All 3GL+ code is basically a string. The "parameter" passed to CREATE FUNCTION is code (to be executed outide the core SQL engine), which is a string (that's not SQL).
Other RDMS's only support SQL as the function/procedure body.

Related

Understanding PostgreSQL & plpgsql defense against code injection

On this very useful page there is this statement...
CREATE OR REPLACE FUNCTION user_access (p_uname TEXT)
RETURNS timestamp LANGUAGE sql AS
$func$
SELECT accessed_at FROM users WHERE username = $1
$func$;
...as an explanation of how to be safe from SQL injection. I am trying to understand why i would be safe this way. What does PostgreSQL do for me, that keeps me safe? Can someone please point me in the right direction?
Why is it safe?
PostgreSQL (and about any other DBMS) will first compile the statement with the $1 in place, and only then will use the actual value provided by the user. So whatever is in the value cannot be interpreted as a part of the statement. In other words, using the parameter separates code from data.
Why do I need a procedure for this?
In most cases, you don't. What you really need is a mechanism that separates code from data, i.e. the parameter. In most languages and DB connectivity libraries nowadays there is a parameterized query support present, which allows you to write queries with placeholders (such as ?) and provide data through a separate parameter.

How to execute a pre-defined query having parameters (i.e. a PARAMETERS declaration) in a Microsoft Access database over ODBC?

My simple question is as follows:
If I have a Microsoft Access database with a defined "query" in it (i.e. the kind of database object that MS Access calls a Query, just to avoid any ambiguity) defined to take parameters (using a PARAMETERS declaration inside its SQL definition) what is the correct SQL syntax to call it over an ODBC connection, including providing the parameter values?
EDIT / ADDITION:
I just noticed that it could be done by adding curly-braces around the entire CALL command, as follows:
{CALL myAccessQuery ('string1', 'string2', 'string3')}
This was actually exactly what they already did in the other related SO thread that I'm referring to here below, but I just thought that this was some C#-specific magic related to the prepared-statement nature of their SQL statement (using "?" in it), or some other peculiarity of their SQL library (I'm not using that language), so I previously ignored it.
Anyone who will explain what the curly-braces are, and why they allow for execution of more SQL commands than the explicitly stated supported ones in the error message below, will be an accepted answer for this question.
Some more details for my specific case:
My query takes three parameters, defined by a "PARAMETERS" clause in the beginning of the query's declaration, as so:
PARAMETERS myParam1 Text ( 255 ), myParam2 Text ( 255 ), myParam3 Text ( 255 );
SELECT ... <a bunch of not relevant stuff here> ;
Using an (already established and confirmed working) ODBC connection, I want to use this query from an external application, including providing the required three parameters for it.
Running normal queries like SELECT etc works just fine over the connection from my external application, but no matter how much I google, I cannot seem to find out the proper way to correctly provide the parameters for and run my query? So, again, my question is, what is the correct SQL syntax for doing this?
NOTE: I do NOT want any API specific solution for some certain library or similar, since this only solves the problem for a very small part of all developers who want to do this from different programming languages, so for this reason, I won't even bring up what language my external application is written in. I just want the full SQL syntax for doing this, nothing more, nothing less.
Another SO question indicates that this should be done using the "CALL" keyword, but when I try to use this from my application, I just get the following error message:
[42000] [Microsoft][ODBC Microsoft Access Driver] Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'.
I.e., this is the "SQL command" (purposely avoiding the ambiguous term "query"...) that I'm trying to execute when getting this error:
CALL myAccessQuery ('string1', 'string2', 'string3')
The only one of the SQL keywords mentioned in the error message that seem likely to be useful is the "PROCEDURE" keyword, but I'm having similarly big difficulties finding any relevant documentation also for this on Google. :-(
I suspect that most of Google's lack of results in regards to this entire scenario comes from the many involved ambiguities regarding more or less all the central keywords in the context, like "queries", "parameters", "execute", "call" and "procedure", so with this SO question my hope is that it will constitute a somewhat more easily identified and indexed answer for this question to be presented by Google in the future.
When you're connecting over ODBC, look at the driver-specific information to see if it supports the various ODBC extensions (indicated by curly braces in the ODBC calls):
https://msdn.microsoft.com/en-us/library/ms675326(v=vs.85).aspx
Specifically:
ODBC provides a specific syntax for calling stored procedures. For the CommandText property of a Command object, the CommandText argument to the Execute method on a Connection object, or the Source argument to the Open method on a Recordset object, passes in a string with this syntax:
"{ [ ? = ] call procedure [ ( ? [, ? [ , … ]] ) ] }"
Each ? references an object in the Parameters collection. The first ? references Parameters(0), the next ? references Parameters(1), and so on.
The parameter references are optional and depend on the structure of the stored procedure. If you want to call a stored procedure that defines no parameters, your string would look like the following:
"{ call procedure }"
The Access ODBC driver exposes saved SELECT parameter queries as Stored Procedures, so that's why you use this syntax.

Oracle SQL Developer: possible to pass parameters to SQL script?

I have the following SQL script (all names replaced with metasyntactic variables):
DELETE FROM FOO
WHERE UPPER(BAR)=? AND UPPER(BAZ)=? AND UPPER(QUX)=? AND UPPER(QUUX)=? AND UPPER(CORGE)=?;
When I run it in SQL Developer, I get the following error, as expected: SQL Error: Missing IN or OUT parameter at index:: 1
Is there a way in SQL Developer to pass test parameters to these values (in this case, BAR, BAZ, QUX, QUUX, and CORGE) or do I have to manually replace the question marks? Thanks!
UPDATE: I've been looking on the internet to try to find the answer with no luck; none of the articles I found deal with the FOO=? syntax. I know that that is the proper syntax to access (and in this case, delete from) the database from a Java program, but I would like to test the SQL script before embedding it in the program.
A query that way is called a prepared statement. It is used as a way to send SQL statements from a program to the database.
First you have to prepare the prepared statement object and later you supply the parameters and finally execute the statement. When setting the parameters, you refer to each question mark in the order they apear in the statement. So in you case, BAR would be parameter 1 and CORGE will be parameter 5.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
For testing a query like this is quite useless in my experience. You could change the paramters to variables or even substitution variables if that is more convenient while testing.
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch5.htm#i1211130

Preventing sql injection - why should one escape the input if using prepared statements?

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.

calling a sql stored procedure using the rows() method in grails?

I am working in a previously existing grails project that has some search functionality built into it. It has created a new Sql object using my SQL Server datasource, and it seems like it is attempting to call a stored procedure like so:
def qResults = sql.rows(spCall)
where spCall is a String and looks like this:
EmployeeQueryClient 'SomeClient', 1,1,0
Where "EmployeeQueryClient is the name of the stored procedure, and the other things are the parameters.
I can't find any documentation supporting this kind of call - is this correct? How would I really do this if it is not?
In the code shown above sql is an instance of groovy.sql.Sql. This provides a rows(String sql) method that can be used to execute SQL and returns the result.
Generally speaking, I think this rows method is a bad choice if you want to call a stored proc, because you have to concatenate the name of the proc and all the args into a single string, which is a bad idea from the point of view of both type safety and readability.
Instead use one of the overload call methods provided by the same class, which are specifically intended for invoking stored procedures. For example, if you just want to invoke the procedure (ignoring any results it returns) use:
sql.call("{call EmployeeQueryClient(?, ?, ?, ?)}", ['SomeClient', 1, 1, 0])
The syntax used here for calling a stored proc,
{call PROC_NAME(PROC_ARGS)}
will work for MySql. If you're not using MySql you'll need to replace this with whatever is used by your RDBMS to invoke a stored proc.
Overloaded versions of the call method enable you to handle any results returned and/or ouput parameters of the stored proc.