Is dollar quoting enough to prevent malicious inputs like SQL injection?
For example:
SELECT * FROM mytable WHERE title = $secret$ hack'-- $secret$
where user input is
hack'--
No, of course not, because the hacker could enter a string containing $secret$.
What you suggest goes by the name “security by obscurity” and enjoys ill respect among security experts. For example, it would not work at all with open source software.
Fortunately PostgreSQL and all relevant APIs have functions that make the safe construction of SQL statements simple.
Related
I feel like I'm missing a very basic concept. I could use some clarification or reference material.
On my website, I have a user that enters text into an input box and submits that to the database to be stored. I insert that text into the database using a function in the code block below where $conn->exec(query) is from Pg.pm.
$conn->exec("select someFunc($mykey,'text to insert');");
Now, this works, but is vulnerable to a sql injection or even if a user enters a comma, it breaks.
I read about DBD::Pg which has the prepare statement which seems what I want, but I could not find the equivalent of this for Pg.pm. Did I miss it?
If Pg.pm does not support prepare. Should I be using a perl module that supports the prepare statement? Or can I just follow the approach outlined at bobby-tables with quote_ident() and quote_literal in my SQL functions that are inserting/updating user-input fields.
How should I be handling user-input in a safe way?
You can not just use quote_ident and quote_literal, because they're at the SQL level, applying to dynamic SQL invoked with EXECUTE. It won't do you any good when passing arguments into the function because the SQL string parsing (and SQL injection attack risk) occurs before the function is even executed with those arguments.
You really need either prepared statement support or a strong, secure literal escaping function that understands PostgreSQL literal quoting rules. If your database driver provides neither then is is unacceptably insecure and should be discarded in favour of one that does.
I’m just starting to convert all of my site’s code into prepared statements for that extra security cushion but I find myself running into the same questions.
After some reading, I’ve decided to use prepared statements on all select queries, however I’m not sure if all of variables in these queries require to be used as “parameters” in the prepared statement.
For example:
Where some_column IS NULL
Where some_column = $_SESSION[‘some-session-var’]
Where some_column IN ($someArray)
Also, is there some way to give each condition a “name” rather than using the question mark? I feel like I’ve seen this before in documentation, but I’ve had no luck finding it since.
For example: Where city_name = :cityName. If so, how would I go about binding the parameters here?
Thanks,
Evan
Yes. All data going to the query should be added via placeholders.
Otherwise there will be no security at all.
Though prepared statements extremely limited and support only scalar values, so, your first and third examples require extra coding (examples can be found in plenty under the tag)
Named placeholders you mentioned belongs to PDO, mysqli don't support them
I would like to offer the possibility to create advanced selects, more profound than the left joins that can be created via quickviewer.
The easiest way would be to allow the user to insert some source code via "GENERATE SUBROUTINE POOL".
But it would be neccesary for me to ensure that this source code doesn't change any data, start other programms or does anything than evaluating data.
My idea would be to restict the inserted source code to some key-worlds like SELECT, LOOP, IF etc. In this case I would need to find all key words in the inserted source code and check it against some white list.
How could I do this? Are there any ways to circumvent my restrictions in order to do some real damage? Are there other ways to reach my goal?
Securing stuff like this is really hard to do, and it's not a personal limitation or an issue with the platform. You can't get the machine to understand what the programmer is doing - see Halting Problem. Doing a keyword scan for yourself is tedious work. You might want to try SCAN ABAP-SOURCE and take a look at the tables the scanner throws out. However, limiting to the most basic language elements will only get you so far, because for any substantial programming, you'll have to allow for external subroutine calls, and then you're vulnerable to about anything. In my opinion, it's better to hand the specifications to a developer and have the report developed with no dynamic stuff whatsoever. This way, you can also ensure that no incorrect reports are created just because the user hacking away at the SELECT statements didn't know about that cancellation flag...
I'm trying to search all tables and columns in a database, a la here. The suggested technique is to construct SQL query strings and then EXEC them. This works well, as a stored procedure. (Another example of variable table/column names is here. Again, EXEC is used to execute "dynamic SQL".)
However, my app requires that I do this in a function, not an SP. (Our development framework has trouble obtaining results from an SP.) But in a function, at least on SQL Server 2008 R2, you can't use EXEC; I get this error:
Invalid use of a side-effecting operator 'INSERT EXEC' within a function.
According to the answer to this post, apparently by a Microsoft developer, this is by design; it has nothing to do with the INSERT, only the fact that when you execute dynamically-constructed SQL code, the parser cannot guarantee a lack of side effects. Therefore it won't allow you to create such a function.
So... is there any way to iterate over many tables/columns within a function?
I see from BOL that
The following statements are valid in a function: ...
EXECUTE
statements calling extended stored procedures.
Huh - How could extended SP's be guaranteed side-effect free?
But that doesn't help me anyway:
The extended stored procedure, when it is called from inside a
function, cannot return result sets to the client. Any ODS APIs that
return result sets to the client will return FAIL. The extended stored
procedure could connect back to an instance of SQL Server; however, it
should not try to join the same transaction as the function that
invoked the extended stored procedure.
Since we need the function to return the results of the search, an ESP won't help.
I don't really want to get into extended SP's anyway: incrementing the number of programming languages in the environment would complicate our development environment more than it's worth.
I can think of a few solutions right now, none of which is very satisfactory:
First call an SP that produces the needed data and puts it in a table, then select from the function which merely reads the result from the table; this could be trouble if the search takes a while and two users' searches overlap. Or,
Have the application (not the function) generate a long query naming every table and column name from the db. I wonder if the JDBC driver can handle a query that long. Or,
Have the application (not the function) generate a long series of short queries naming every table and column name from the db. This will make the overall search a lot slower.
Thanks for any suggestions.
P.S. Upon further searching, I stumbled across this question which is closely related. It has no answers.
Update: No longer needed
I think this question is still valid, and we may again have a situation where we need it. However, I don't need an answer anymore for the present problem. After much trial-and-error I managed to get our application framework to retrieve row results from the RDBMS via the JDBC driver from the stored procedure. Therefore getting the thing to work as a function is unnecessary.
But if anyone posts an answer here that helps with the stated problem, I will be happy to upvote and/or accept it as appropriate.
An sp is basically a predefined sql statment with some add ons.
So if you had
PSEUDOCODE
Create SP_DoSomething As
Select * From MyTable
END
And you can't use the SP
Then you just execute the SQL as in "Select * From MyTable"
As for that naff sql code.
For start you could join table to column with a where clause, which would get rid of that line by line if stuff.
Ask another question. Like How could this be improved, there's lots of scope for more attempts than mine.
I'm currently doing some maintenance on an application and I've come across a big issue regarding the qualified name in tsql. I wondering if someone could clear my confusion up for me.
From my understanding you want to use USE [DatabaseName] to declare which database you are using. I notice if u "rename" the databse it automatically updates these references in your code.
However, the developer who originally wrote this code used the USE [DatabaseName]. Then in later statements he wrote: SELECT * FROM [DatabaseName].[dbo].[Table]. Well this obviously breaks if I change the Database's name. From what i've read you want to qualify names only to the owner such as: [dbo].[TableName] so it knows where to look which increases performance.
Is there a reason he included the Database name in each statement?
From what i've read you want to qualify names only to the owner such as: [dbo].[TableName] so it knows where to look which increases performance.
Not that I'm aware of, rather it looks like someone is lazy.
I always use the three name format (unless accessing a linked server instance, then it's four).
The benefit is that the correct table from the correct database & schema will be used without concern for an errant USE [appropriate database] statement. As long as the object exists, and the permissions are valid based on the need, you can recreate a stored procedure, function, view, etc in other databases without needing to address the USE [appropriate database] statement each time.
But I'm working with data spread over numerous databases on the same instance. I wouldn't have necessarily designed it that way, but it wouldn't change that I use three (or four) part qualified name format.