How to check if string is query? Protect from sql injection; - sql

I use Spring + Hibernate.
In one part I have native sql like:
SELECT *
FROM (...) sel
WHERE %s
%s i receive from UI. It looks like "id = ?1 AND name = ?2..." + list of params.
It is generated by query builder;
And now i have a case when UI can send something like:
CLAUSE: id = 'id; TRUNCATE TABLE schema.foo;'
How to check that clause is not a query?
Where can i find some libraries?

I would take an other direction : rather than trying to detect if a query is malicious, make sure that the query cannot do anything malicous, with grants at database level :
if you have a public table, with users generating queries for this table, create a database user that can only SELECT on this sole table, and use a specific jdbc connection, that connect to the database using the former read-only user, to run these 'unsafe' queries.

Related

Documentum -- Custom queries

I am new to learning Documentum and we came across this query being run by the system that we are looking at how to potentially speed up:
SELECT ALL dm_document.r_object_id
FROM dm_document_sp dm_document
WHERE (
dm_document.object_name = :"SYS_B_0"
AND dm_document.r_object_id IN (
SELECT r_object_id
FROM dm_sysobject_r
WHERE i_folder_id = :"SYS_B_1"
)
)
AND (
dm_document.i_has_folder = :"SYS_B_2"
AND dm_document.i_is_deleted = :"SYS_B_3"
)
We looked at adding an index or using a SQL profile. However, the index would be somewhat large and will continue to grow. The SQL profile also would need to be re-examined periodically.
We thought it would be better to look at re-writing the SQL itself. Is there a way to override the system to use custom SQL (i.e. SQL written by the developers) for specific queries that Documentum auto-generates?
Unfortunately there is no way how to alter the default Documentum behavior of translation of DQL into result SQL.
But you can directly execute SQL in your custom applications, jobs, BOFs, components, etc using JDBC. For other than SELECT queries can be also used DQL EXECUTE statement like this:
EXECUTE exec_sql WITH query = 'sql_query'
Another option is to register specific *_s or *_r tables and access them directly in DQL. For example you can register dm_sysobject_s like this:
REGISTER TABLE dm_dbo.dm_sysobject_s ("r_object_id" CHAR(16))
And then you can use it in DQL:
SELECT object_name FROM dm_sysobject_s
And you can also normally join the registered table with Documentum types in DQL, for example:
SELECT object_name FROM dm_sysobject_s s, dmi_queue_item q WHERE s.r_object_id = q.item_id
But keep in mind that this is not recommended approach by Documentum to directly access their internal tables but when you really need to speed up your application then you have to use alternative ways.
Anyway I would recommend to use indexes at first and if it is not suficent then you can continue with steps described above.

Why do Parameterized queries allow for moving user data out of string to be interpreted?

From https://en.wikipedia.org/wiki/Code_injection#Preventing_problems
To prevent code injection problems, utilize secure input and output handling, such as:
Using APIs that, if used properly, are secure against all input characters. Parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted. Additionally Criteria API[7] and similar APIs move away from the concept of command strings to be created and interpreted.
I was wondering how and why "parameterized queries (also known as "Compiled queries", "prepared statements", "bound variables") allows for moving user data out of string to be interpreted" and prevent or mitigate code injection problems?
Can you also provide some examples in explanation?
Thanks.
Compiled queries use special syntax that the database understands. They usually add placeholders for parameters such as in:
select * from applicant where name = ?
select * from applicant where name = :name
The exact syntax depends on the specific technology: JDBC, ODBC, etc.
Now, once those queries are sent to the database (without the specific parameter values), the database "saves" them. Later on (usually in the same database session), you can run them many times, by just providing the parameter values each time.
SQL Injection Safety
They are also safe against SQL injection. For example, if in the previous query instead of a simple value such as Mary you used the value x'; delete from applicant; -- the database will work safely. It would run something like:
select * from applicant where name = 'x; delete from applicant; --'
This query won't probably find anything and will be safe.
If instead you didn't use compiled query, but just decided to concatenate the SQL as a string you would do something like:
String sql = "select * from applicant where name = '" + param1 + "'";
And would end up with the UNSAFE query:
select * from applicant where name = 'x'; delete from applicant; --
This one would run two queries. The second one will delete all the information from your table. Probably not what you want.

SQL Server - Syntax around UNION and USE functions

have a series of databases on the same server which i am wishing to query. I am using the same code to query the database and would like the results to appear in a single list.
I am using 'USE' to specify which database to query, followed by creating some temporary tables to group my data, before using a final SELECT statement to bring together all the data from the database.
I am then using UNION, followed by a second USE command for the next database and so on.
SQL Server is showing a syntax error on the word 'UNION' but does not give any assistance as to the source of the problem.
Is it possible that I am missing a character. At present I am not using ( or ) anywhere.
The USE statement just redirects your session to connect to a different database on the same instance, you don't actually need to switch from database to database in this matter (there are a few rare exceptions tho).
Use the 3 part notation to join your result sets. You can do this while being connected to any database.
SELECT
SomeColumn = T.SomeColumn
FROM
FirstDatabase.Schema.TableName AS T
UNION ALL
SELECT
SomeColumn = T.SomeColumn
FROM
SecondDatabase.Schema.YetAnotherTable AS T
The engine will automatically check for your login's users on each database and validate your permissions on the underlying tables or views.
UNION adds result sets together, you can't issue another operation (like USE) other than SELECT between UNION.
You should use the database names before the table name:
SELECT valueFromBase1
FROM `database1`.`table1`
WHERE ...
UNION
SELECT valueFromBase2
FROM `database2`.`table2`
WHERE ...

SQL Injection without direct user input

In order to prevent SQL Injection for my site, i have used prepared statements.
Now let's say i use somewhere in my code, a simple SQL query like this :
SELECT DATA FROM DATABLE;
Is this code prone to injection ? Well it seems to me that's not possible to be, as there is no user input.But i just want to be sure.
If your statement is fixed (has no outside parameters), then it is immune to injection.
So if your code looks something like this:
result = RunQuery("SELECT * FROM Table")
then you are safe, since the query will always be the same everytime and cannot be influenced by users.
Inject is only possible if you use a variable in your query.
If you use prepaired statements with params it is not possible.
select * from user where id = ?
You cannot change this query, only the value, in that case you will just get no results
If you use
select * from user where id = '$id'
now depending on the value of $id we can have a sql inject.
If $id would be "0' or id > 0 " you will allways login ;)

Parse Oracle Query using perl

I have to perform lexical analysis on the oracle query and separate the query to various parts (based on the clauses)in perl. For example,Consider :
Select deleteddate,deletedby from temptable where id = 10;
I need to print
select : deleteddate , deletedby
from : temptable
where : id = 10
I used this code snippet :
my $parser= SQL::Statement->new();
$parser->{PrinteError}=1;
my $query = SQL::Statement->new("select deleteddate,deletedby from temptable where id =10",$parser);
my #columns = $query->columns();
print $columns[0]->name();
Though this prints deleteddate, this fails when i give a subquery inside the select clause:
Select deleteddate,deletedby,(select 1+1 from dual) from temptable where id = 10;
Can you please point me in the correct direction.
Thanks.
It looks to be a limitation of that package; it seems to be a general purpose parser and not something that can understand advanced features like subqueries or Oracle-specific constructs like "from dual".
What are the constraints of your system? If python is an option it looks like this is a more fully-featured library:
http://code.google.com/p/python-sqlparse/
The other option would be to use the actual Oracle database, if that's an option. You would:
use the DBI and DBD::Oracle modules to create a connection to Oracle & get a database handle,
create a statement handle by calling prepare() on the database handle using your query,
execute the query (there may be an option in Oracle to execute in "test only" or "parse only" mode),
examine the statement handle (such as the NAMES_hash property) to get the column names.
Otherwise it seems the SQL::Statement module unfortunately just isn't up to the task...