Which query injection breaks this SQL if input is validated again regex? - sql-injection

SELECT COLUMN_NAME FROM TABLE_NAME WHERE COLUMN_NAME = {INPUT};
I don't have a connection directly to a database, so I have to send the query as string. I will validate the input value against this pattern "[a-zA-Z]\s[a-zA-Z]", so I haven't found a way to break this query.

I think you meant [a-zA-Z]\s[a-zA-Z].
Seems to works on all examples of this page:
http://www.unixwiz.net/techtips/sql-injection.html

Related

PostgreSQL, allow to filter by not existing fields

I'm using a PostgreSQL with a Go driver. Sometimes I need to query not existing fields, just to check - maybe something exists in a DB. Before querying I can't tell whether that field exists. Example:
where size=10 or length=10
By default I get an error column "length" does not exist, however, the size column could exist and I could get some results.
Is it possible to handle such cases to return what is possible?
EDIT:
Yes, I could get all the existing columns first. But the initial queries can be rather complex and not created by me directly, I can only modify them.
That means the query can be simple like the previous example and can be much more complex like this:
WHERE size=10 OR (length=10 AND n='example') OR (c BETWEEN 1 and 5 AND p='Mars')
If missing columns are length and c - does that mean I have to parse the SQL, split it by OR (or other operators), check every part of the query, then remove any part with missing columns - and in the end to generate a new SQL query?
Any easier way?
I would try to check within information schema first
"select column_name from INFORMATION_SCHEMA.COLUMNS where table_name ='table_name';"
And then based on result do query
Why don't you get a list of columns that are in the table first? Like this
select column_name
from information_schema.columns
where table_name = 'table_name' and (column_name = 'size' or column_name = 'length');
The result will be the columns that exist.
There is no way to do what you want, except for constructing an SQL string from the list of available columns, which can be got by querying information_schema.columns.
SQL statements are parsed before they are executed, and there is no conditional compilation or no short-circuiting, so you get an error if a non-existing column is referenced.

Is this actually open to SQL injection?

We have a function that builds some XML and uses EXECUTE/USING to try to prevent SQL injection. It's along the lines of:
CREATE OR REPLACE FUNCTION public.f1(t TEXT)
RETURNS XML AS
$BODY$
DECLARE
ret_val XML;
BEGIN
EXECUTE 'SELECT ''<'' || $1 || ''>'''
--rest of xml building
INTO ret_val
USING t;
RETURN ret_val;
END
$BODY$
LANGUAGE plpgsql IMMUTABLE;
I don't like this much due to the concatenation. It would be much better if we could just do SELECT '''<$1>'' but that ends up with a literal $1 rather than replacing it with the value.
Due to the concatenation, it's making me wonder whether we even need SQL injection prevention here. It's not reading from a table, just building an XML string which is returned.
Is there any actual risk from not using USING in this case? Does concatenating $1 negate the effects of USING, or does USING even have any effect on a statement that doesn't use a table?
There are a few things to unpack here.
Firstly, the SQL you have there is actually a fixed string:
'SELECT ''<'' || $1 || ''>'''
So nothing can be directly injected here, because there's no dynamic SQL. As Laurenz Albe pointed out, the SQL in this particular example could be written as a non-dynamic statement:
SELECT '<' || t || '>'
There is still no SQL injection here, because you're not evaluating the contents of t, just manipulating it as a string, just as SELECT a + 1 would manipulate a as a number.
The key point is that the actual SQL is hard-coded, and the concatenation is just the instruction in that SQL.
Note that this similar-looking query would be dangerous (the syntax highlighting gives a clue to the difference):
EXECUTE 'SELECT ''<' || t || '>''' -- DON'T DO THIS!
Here, the value of t is being used as part of the SQL string - the concatenation is happening first, and then the result is executed. So a value of '1'; DROP TABLE users; --' would result in the query SELECT '<1'; DROP TABLE users; -- which is clearly undesirable.
Secondly, as explained in the docs, the $1 is a parameter, supplied by the USING clause as data, so it too is safe from SQL injection. This is similar to using a parameterised query in a programming language outside the database - you build up the query as a string, carefully whitelisting the tables and columns referenced, then provide the variable data separately, where it cannot be reinterpreted as SQL. Or to put it another way, it's like another function "one level deeper", with the parameters specified by the USING clause acting just like the parameters to an actual function.
Finally, though, a note of caution: you are vulnerable to XML injection: if nothing else has validated or escaped t, you could generate invalid or dangerous XML. For instance, consider what would happen if the value of t was 'foo><script>alert("Hello, world!");</script></foo' and the result ended up parsed as HTML.
There is no danger for SQL injection here, because you are using USING.
Note that you could have been using static SQL to achieve the same thing:
SELECT '<' || t || '>' INTO ret_val;

How to escape underscores in Postgresql

When searching for underscores in Postgresql, literal use of the character _ doesn't work. For example, if you wanted to search all your tables for any columns that ended in _by, for something like change log or activity information, e.g. updated_by, reviewed_by, etc., the following query almost works:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%_by'
It basically ignores the underscore completely and returns as if you'd searched for LIKE '%by'. This may not be a problem in all cases, but it has the potential to be one. How to search for underscores?
You need to use a backslash to escape the underscore. Change the example query to the following:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%\_by'
Just ran into the same issue and the single backslash wasn't working as well. I found this documentation on the PostgreSQL community and it worked:
The correct way is to escape the underscore with a backslash. You
actually have to write two backslashes in your query:
select * from
foo where bar like '%\\_baz'
The first backslash quotes the second one for the query parser, so
that what ends up inside the system is %\_baz, and then the LIKE
function knows what to do with that.
Therefore use something like this:
SELECT table_name, column_name FROM information_schema.columns
WHERE column_name LIKE '%\\_by'
Source Documentation: https://www.postgresql.org/message-id/10965.962991238%40sss.pgh.pa.us

SPLIT_PART() not returning results in Redshift

There are strings in a Redshift database that I'm trying to parse. The strings look like this in the object field:
yada \n foobar\n thisthing: xyz\nvegetable: amazing
The value I'm trying to get at is xyz.
I'm trying:
SELECT split_part(v.object::varchar,'\n',3) as first_parse
FROM table_name as v
Believing that will return thisthing: xyz which I can then split again on ': '.
The Redshift documentation makes me think that's valid Redshift SQL:
http://docs.aws.amazon.com/redshift/latest/dg/SPLIT_PART.html
This answer on StackOverflow also makes me believe this is valid Redshift SQL:
https://stackoverflow.com/a/20811724/1807668
However the results of that query are results that are blank in the first_parse field (not NULL, actually blank).
How should I go about getting to the xyz part of my sample string above using Redshift SQL? Any help would be appreciated.

SQL Server 2000 query that omits commas in resulting rows?

Wondering if there is a way to query a SQL Server database and somehow format columns to omit commas in the data if there is any.
Reason for asking is I have 10000+ records and through out the data the varchar have data like 3,25% and other 1%.
I'd prefer not to alter the data in the original table thus asking if a select with other functions would do the trick.
I have thought about selecting all the data into a temp table and stripping the commas but that is a lot of work for every time I do the query.
Any info or if its is possible please reply.
Take a look at the REPLACE function:
SELECT REPLACE(YourColumn, ',', '')
FROM YourTable
Use SQL REPLACE :
REPLACE(YourField,',','')