For eg. i have:
Input:
ArrayList<Integer> idlist
String nameText
String q = "DELETE FROM myTable AS a WHERE a.name LIKE '%' || :name || '%' OR a.id IN (:idlist)";
Query query = entityManager.createQuery(q);
query.setParameter("name", nameText);
query.setParameter("idlist", idlist);
query.executeUpdate();
Would the above snippet of code susceptible to sql injections?
I have one more question is there a diffrence between the way above query is built and if we form query by criterias:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
q.select(c);
Is there any advantage of one over another?
No, it wouldn't. That's the whole point of parameterized queries.
There is no chance for SQL injection with prepared statements.
But if the values of parameter are entered by users, the expression LIKE % || :name || % can be misused by entering only one letter and deleting all the records that contain that letter anywhere in the a.name column
Related
The Django generating sql queries with function calls in where clause like below, when using Django queries for search or any other purposes.
SELECT COUNT(*) AS "_count"
FROM "products_product"
INNER JOIN "products_productmeta" ON ("products_product"."meta_id" = "products_productmeta"."id")
WHERE ((NOT ("products_product"."archived" = true) AND
"products_product"."owner_id" = 1281 AND
UPPER(UNACCENT("products_product"."sku")::text) LIKE '%' ||
UPPER(REPLACE(REPLACE(REPLACE((UNACCENT('octavi')), '\', '\'), '%', '\%'), '', '_')) ||
'%') OR
(NOT ("productsproduct"."archived" = true) AND
"products_product"."owner_id" = 1281 AND
UPPER(UNACCENT("products_productmeta"."name")::text) LIKE '%' ||
UPPER(REPLACE(REPLACE(REPLACE((UNACCENT('octavi')), '\', '\'), '%', '\%'), '', '_')) ||
'%')
)
Response time is taking too long with these type of queries because of whole data sets are passing through the function calls.
Is there any way to avoid those function calls such as UPPER, REPLACE etc... in where clause of sql generated by django?
Is writing raw sql queries the only option?
EDIT: Django query example with SQL string output added:
Product.objects.filter(meta__name__icontains="foo").query.sql_with_params()
The simple Django query above is generating SQL string below:
('SELECT
"products_product"."id",
....
"products_product"."is_primary"
FROM "products_product"
INNER JOIN "products_productmeta" ON ("products_product"."meta_id" = "products_productmeta"."id")
WHERE (NOT ("products_product"."archived" = %s) AND
UPPER("products_productmeta"."name"::text) LIKE UPPER(%s))',
(True, '%foo%'))
As you can see; Django adding function calls to where clause. I want to remove that function calls. Complex queries are taking too long time.
I try to join two tables using Arel to generate some SQL like this:
[...]
INNER JOIN "nodes" ON "nodes"."id" LIKE "jobs"."ancestry" || '%'
[...]
to match any job that starts with one of the node IDs. When I run the plain SQL this works, now I try to build this with Arel:
node = Node.arel_table
job = Job.arel_table
node.join(job).on(node[:id].matches("_______%"))
Now I can't find anything how to get the right string for matches, even if I try:
"\"nodes\".\"ancesty\" || %"
the full string will be escaped. Is there any way to pass raw SQL the the Arel matches method that will not be escaped or any other way to get this working with Arel?
It seems Arel::Nodes::SqlLiteral does the job:
node = Node.arel_table
job = Job.arel_table
lit = Arel::Nodes::SqlLiteral.new("_______%")
node.join(job).on(node[:id].matches(lit))
I have a table that contains a column storing sql functions, column names and similar snippets such as below:
ID | Columsql
1 | c.clientname
2 | CONVERT(VARCHAR(10),c.DOB,103)
The reason for this is to use selected rows to dynamically create results from the main query that match spreadsheet templates. EG Template 1 requires the above client name and DOB.
My Subquery is:
select columnsql from CSVColumns cc
left join Templatecolumns ct on cc.id = ct.CSVColumnId
where ct.TemplateId = 1
order by ct.columnposition
The results of this query are 2 rows of text:
c.clientname
CONVERT(VARCHAR(10),c.DOB,103)
I would wish to pass these into my main statement so it would read initially
Select(
select columnsql from CSVColumns cc
left join Templatecolumns ct on cc.id = ct.CSVColumnId
where ct.TemplateId = 1
order by ct.columnposition
) from Clients c
but perform:
select c.clientname, CONVERT(VARCHAR(10),c.DOB,103) from clients c
to present a results set of client names and DOBs.
So far my attempts at 'injecting' are fruitless. Any suggestions?
You can't do this, at least not directly. What you have to do is, in a stored procedure, build up a varchar/string containing a complete SQL statement; you can execute that string.
declare #convCommand varchar(50);
-- some sql to get 'convert(varchar(10), c.DOB, 103) into #convCommand.
declare #fullSql varchar(1000);
#fullSql = 'select c.clientname, ' + #convCommand + ' from c,ients c;';
exec #fullSql
However, that's not the most efficient way to run it - and when you already know what fragment you need to put into it, why don't you just write the statement?
I think the reason you can't do that is that SQL Injection is a dangerous thing. (If you don't know why please do some research!) Having got a dangerous string into a table - e.g 'c.dob from clients c;drop table clients;'- using the column that contains the data to actually execute code would not be a good thing!
EDIT 1:
The original programmer is likely using a C# function:
string newSql = string.format("select c.clientname, {0} from clients c", "convert...");
Basic format is:
string.format("hhh {0} ggg{1}.....{n}, s0, s1,....sn);
{0} in the first string is replaced by the string at s0; {1} is replaces by tge string at s1, .... {n} by the string at sn.
This is probably a reasonable way to do it, though why is needs all the fragments is a bit opaque. You can't duplicate that in sql, save by doing what I suggest above. (SQL doesn't have anything like the same string.format function.)
In traditional sql we can chain expression according to if statements.
for example lets say I have variable called "firstName" and I want to get from database all users according to the value in this variable(if empty get all users)
so I will chain the sql string like that
string sql="";
if(firstname!="")
sql=String.format(" And firstname='{0}',firstName)
.ExecuteReader(System.Data.CommandType.Text,"select * from users where 1=1" + sql)
Is there a way to copy this Technique to linq expression?
something like
from U in user
where 1=1 & sql
select U
Change to method syntax instead of query syntax, and chaining is easy.
var query = user.Select(u => u);
if(firstname!="")
query = query.Where(u => u.firstname = firstname);
queries in query syntax are converted at compile-time, so there's not a mechanism to "inject" sql at run time using query syntax.
Suppose we need to check three boolean conditions to perform a select query. Let the three flags be 'A', 'B' and 'C'.
If all of the three flags are set to '1' then the query to be generated is
SELECT * FROM Food WHERE Name In ('Apple, 'Biscuit', 'Chocolate');
If only the flags 'A' and 'B' are set to '1' with C set to '0'. Then the following query is generated.
SELECT *
FROM Food
WHERE Name In ('Apple, 'Biscuit');
What is the best way to do it?
SELECT *
FROM Food
WHERE (Name = 'Apple' AND <condition A>)
OR (Name = 'Biscuit' AND <condition B>)
OR (Name = 'Chocolate' AND <condition C>)
Now, while being correct this is not desirable from performance point of view since conditions A, B, and C are not data driven (they don not change from row to row). So you can use permutations of all possible conditions by constructing SQL dynamically - use IN clause and construct its string dynamically.
Yet another solution is assembling final result in the client by running each SELECT separately (pseudo-code):
if A then {
result1 = execute("SELECT * FROM Food WHERE Name = 'Apple')
}
if B then {
result2 = execute("SELECT * FROM Food WHERE Name = 'Biscuit')
}
if C then {
result2 = execute("SELECT * FROM Food WHERE Name = 'Chocolate')
}
result = join(result1, result2, result3)
This solution may work when you have high percentage of cases with just one or two true conditions.
First may be you need to check if all are false and show error. Or may be not if it is acceptable in your case.
Then if these flags are mere bool variables do (pseudocode)
sql = "SELECT *
FROM Food
WHERE Name In (";
if (A) sql += "'Apple', "
if (B) sql += "'Biscuit', "
if (C) sql += "'Chocolate', "
sql = sql.deleteLastCharacter() + ");";
Why don't you include A/B/C in the query?
select * from food where (name = 'Apple' or NOT A) and (name = 'Biscuit' OR NOT B)...
I think this should be read: Dynamic SQL.
The sp_executesql system stored procedure reveals to be pretty useful also.
This is a really complex topic that has many subtle performance implications. You really need to read these excellent articles by Erland Sommarskog:
Dynamic Search Conditions in T-SQL
The Curse and Blessings of Dynamic SQL