Prepared statements (LIKE, ORDER BY) - sql-injection

I'm trying to fix up SQL request by using prepared statements but looks like it works in some different way with the LIKE operator, I have the following request:
db.execute("SELECT * FROM article WHERE title LIKE '%%%s%%' ORDER BY created_at %s"
% (search_title, order_by))
I tried to rebuild it into the prepared statement like:
pattern = "%%" + search_title + "%%"
articles = db.execute("SELECT * FROM article WHERE title LIKE (pattern = %s) ORDER BY created_at (order_by = %s)", [pattern, order_by])
but it breaks the query.
I understand that usually, the pattern for the prepared statement in Python is like this:
cursor.execute("SELECT admin FROM users WHERE username = %s'", (username, ));
But could anyone please explain to me how to re-build more complex and difficult SQL requests because all examples that I googled were really simple?

Related

What is the TABLE keyword for in this CTE expression

in this I post came across this weird postgres query:
WITH max_i AS
( SELECT MAX(i) FROM test )
SELECT *
FROM test
WHERE i = (TABLE max_i) - 1 ;
It was able to use the CTE return value like a simple variable through the use of the TABLE keyword. I looked through the documentation of postgres, but I couldn't find any mention of what it is or what it is used for. Can someone explain to me how it works?
It's a short way of writing
select * from max_i
See the manual for details

Get the ResultSet of an SQL injection

Suppose the server side code is something like that:
String id = getIdFromHttpRequest();
String value = getValueFromHttpRequest();
ResultSet rs = new ResultSet();
String query = "INSERT INTO users VALUES ('" + id + "', '" + value + "');"
rs = SQL.doQuery(query); // i know it's not the syntax, but the point is clear
Well, the injection is easy, I can make it execute an SQL command, but the problem is I want to see the result set (I inject SELECT command).
Is there a way of doing so?
You probably cannot achieve this.
As you know, an INSERT statement has no result set, even if you use SQL injection. At best, you could make it execute a SELECT as a scalar subquery. It's not hard to spoof your example to execute the following:
INSERT INTO users VALUES ('8675309', '' || (SELECT ...blah blah...) || '');
But that still would not return a result set, because INSERT never has a result set.
You would need to execute a second query to do that. Some query interfaces do support multi-query in a single call to doQuery(), but this is not always true (depends on the brand of database you use, and possibly some configuration options).
INSERT INTO users VALUES (...whatever...);
SELECT * FROM secure_table WHERE (id = '8675309');
With SQL injection, you can manipulate the SQL, but you can't manipulate the rest of the code in the application that runs the SQL. In the example you show, the app is designed to run an INSERT query, not an INSERT followed by a SELECT. The app would have no reason to fetch a result set after executing an INSERT.
It's hard to imagine how you could use SQL injection alone to trick the code you show into fetching and displaying a result set.
I don't think it is possible to use SQL injection do read data by exploiting a non-reading query.

SQL Injection : Syntax error

I have an essay on SQL injection ( what it is - how its done and how can it be avoided ). I get what it is and how it works. But i dont seem to be able to reproduce an injection on my database.
I made a pretty simple database ,using mysql workbench, meant for a video club. movies - stock - price - customers shopping cart etc.
I also made a pretty simple html page from which i can add movies - view what i have in stock etc.
So i have a txt field in which i enter a movie name and i get back some info for this specific movie.
The code that gets the name i type and makes the query is ::
$name = $_POST ['txtfld'];
$sql = ("SELECT * FROM test_table WHERE adad = '$Mname'");
if ($result = mysqli_query($dbc,$sql))
Now when i give 'a' as an input everything works as expected. I get back the one entry that has pk equal to [a].
Query becomes :: SELECT * FROM test_table WHERE adad= 'a'.
Next step was to see if i can get the whole table or some random entry from it.
Input was : [ a' OR 'x'='x ]
Query becomes :: SELECT * FROM test_table where adad = ' a' OR 'x' = 'x '
Everything works as expected and i get back the whole table contents.
Next step was to try inject a second query. I tried to update the test_table.
Input was :: [ a;' update test_table set asda = '123456' where adad = 'u ]
Query now becomes :: SELECT * FROM test_table WHERE adad= ' a;' UPDATE test_table SET asda ='123456' WHERE adad = 'u '
I got a syntax error so i tried every syntax i could think of including
[ a;' UPDATE test_table SET asda = '123456' where adad = 'u';# ]
. None of them worked.
Thing is, i dont really get why i get a syntax error.
For the input given above mysqli_error returns this message
error: You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'update test_table set asda =
'123456' where adad = 'u'' at line 1
while an echo i inserted returns this
SELECT * FROM test_table WHERE adad = 'a;' UPDATE test_table SET asda = '123456' WHERE
adad = 'u'
I dont see any syntax error in the echo return and i dont get where the second [ ' ] character in the end of the mysqli_error return, comes from.
From what i understand this is rather a failure in executing a second query ( no matter what the query is - drop, insert, update )
Do i miss something?
Thanks in advance.
Michael.
mysql's PHP driver does NOT allow multiple queries in a single ->query() call, exactly for this reason. It's an anti-injection defense, to prevent the classic Bobby Tables attack. This true for all PHP db interfaces (mysql, mysqli, pdo), as they all use the same underlying mysql C api library to actually talk to the db. Any attempt to run 2+ queries in a single query call results in the syntax error.
Note that it does NOT protect against your ' or 1=1 injection, however.
In order for your stacked query injection technique to work, you will need to use the "mysqli_multi_query()" function:
http://php.net/manual/en/mysqli.multi-query.php
http://www.websec.ca/kb/sql_injection#MySQL_Stacked_Queries
MsSQL is the only database that supports stacked queries by default.
Also possibly a better injection technique, and a more reliable one, would be a UNION attack, and then dump the MySQL credentials from the "mysql.user" table, then use these to compromise the database.

SQL Server openrowset() test column count in MS Access table

Haven't found an answer via Google. I need to execute this code from SQL Server stored proc.
I have a folder with 100+ access dbs with a table called tblReports. Some of the access db's have an extra column in tblReports called AdminReport.
I need to capture the extra column if it exists, thus... I need to test how many columns are in tblReports so that I can use an if/else statement in the sp to generate the correct sql based on the column count.
I'd love to read your thoughts, here's the relevant snippet.
set #sql = 'Insert into CustomerServiceIntranet.dbo.ReportCriteria
(UserInfo,RptNbr,RptType,RptDesc,GroupCDBrk,ClientCDBrk,CategoryCDBrk,
UserIDBrk,UnitCDBrk,WrkTypeBrk,StatCDBrk,StatDatBrk,
ExperBrk,GroupList,ClientList,CategoryList,UserIDList,BusAreaList,
WrkTypList,StatusList,QueueList,ReviewDay,ReviewDayNA,
ErrorImpact,DateRange,DataSource,RptPathFile)'
+ 'Select '''+ #userfilename + ''', ors.* '
+ 'from (select * From Openrowset(''Microsoft.ACE.OLEDB.12.0'','''
+ #CurrentName
+ ''';''Admin'';,''select * from tblReports'')) ors'
The standard approach would be to link to tblReports by calling DoCmd.TransferDatabase. You would then be able to count number of the fields in the table, before embarking on any SQL. At the end of the look you would delete the link by calling DoCmd.DeleteObject.
It certainly looks neater than what you are trying to do.

Re-write this Query to make it more scalable

I have a page on my site which has multiple drop down boxes as filters.
So the SQL procedure for that page would be something like this
IF #Filter1 = 0, #Filter2 = 0, #Filter3 = 0
BEGIN
SELECT * FROM Table1
END
ELSE IF #Filter1 = 1, #Filter2 = 0, #Filter3 = 0
BEGIN
SELECT * FROM Table2
END
At the beginning, there were only a few results per filter so there weren't that many permutations. However, more filters have been added such that there are over 20 IF ELSE checks now.
So if each filter has 5 options, I will need to do 5*5*5 = 125 IF ELSE checks to return data dependent on the the filters.
Update
The first filter alters the WHERE condition, the second filter adds more tables to the result set, the third filter alters the ORDER BY condition
How can I make this query more scalable such that I don't have to write a new bunch of IF ELSE statements to check for every condition everytime a new filter is added to the list besides using dynamic SQL...
You must have to have a rule table with formulaes maybe bitwise and construct a query that might plug variable data from the table and appends to a string to form the sql and the use dynamic sql to run them.
As much as I dislike dynamic SQL, this may be the time for it. You can build the query a little at a time, then execute it at the end.
If you're unfamiliar, the syntax is something like:
DECLARE #SQL VARCHAR(1000)
SELECT #SQL = 'SELECT * FROM ' + 'SOME_TABLE'
EXEC(#SQL)
Make sure you deal with SQL injection attacks, proper spacing, etc.
In this case, I'd do my best to put this logic in application code, but that's not always possible. If you're using LINQ-to-SQL or another LINQ framework, you should be able to do this safely, but it may take some creativity to get the LINQ query built properly.
You can set up a bunch of views, one for each "filter" and then select from the appropriate view based on which "filter" was selected.