I have a long running select query on an embedded H2 Database and want to allow the user to cancel the query.
How can this be done? I cannot find anything about this.
[UPDATE]
To be more specific I'm running my query using JPA. How can the query be stopped?
H2 supports a query timeout setting. You can set this in the database URL as follows: jdbc:h2:~/db/test;query_timeout=10000. (Maybe this is not the right approach for you, but it might be for others that read this question.)
You can also cancel a query running in another connection (session) using the cancel_session function. But for this you need to enable the multi-threaded mode, which is currently not recommended for production use (it is still experimental in version 1.3.175).
If you have a few queries which might take very long, then don't use JPA for them. Create your own statement so you can cancel it.
Alternatively, get the source code for a JDBC proxy like log4jdbc and add code that allows you to get connections and statements per thread. That would allow you to get the statement after JPA has sent it to the proxy.
Related
I have doubts between two options:
Build the query in client side and send it to server.
Sending from client the needed knowledge in order to build the query in server side.
In which side I will prefer to build the query?
Advantages / Disadvantages?
Thanks.
I tend to prefer building queries on the server side and either storing them as Stored Procedures on the sql server or building the query string in a backend language like PHP.
Building the query in something like javascript and sending to the server, creates the possibility of deviants doing inline altering of your javascript and submitting the query string through something like firebug. If you build the query string in a backend (server-side) language, the only thing the user would have access to alter would be input variables (if applicable). Because of this, you should always check and cleanse all input variables for sql injection.
Removing as much access to raw code from the end user as possible seems to always be the best option, in terms of application security. Someone else may weigh-in about performance limitations; but if a user alters and submits their own query string through a javascript console and drops your entire table, performance won't really be a factor anymore will it?
Here's an example of the sort of query I would like to prevent from running on my server:
begin
While True
LOOP
dbms_output.put_line('tst');
END LOOP;
end
This query (or others like it) may be hitting my Oracle server via the Oracle JDBC thin driver. I would be open to preventing this query from running either at the JDBC configuration level, the database server configuration level, or via user permissions within the schema. I would like the user to continue to be able to run normal select/insert/update/delete queries. Honestly I'd be quite happy if none of the PL/SQL type commands were available, and instead only standard SQL.
Update
I should also mention that I want users to continue to be able to use standard functions in their SQL queries. I just really don't want them doing anything that looks like procedural programming (and having to worry about the pitfalls of such things, as seen above).
You can't prevent people from writing procedural PL/SQL code against your server. Depending on the exact nature of the problem you're trying to solve, however, you may have other options. Two options that spring to mind...
You can create a profile associated with the database user that enforces various resource limits. So you can limit the amount of CPU a single call can consume or the number of reads it can do. That lets you automatically kill sessions that do something like coding an infinite loop. Note that the RESOURCE_LIMIT initialization parameter needs to be set to TRUE in order for Oracle to enforce resource limits in profiles.
You can use Oracle Resource Manager to prioritize access to resources to reduce the risk that a developer's mistake will take all the resources available on the server and starve the important production processes.
It seems that one could stop all threat of Sql injection once and for all by simply rejecting all queries that don't use named parameters. Any way to configure Sql server to do that? Or else any way to enforce that at the application level by inspecting each query without writing an entire SQL parser? Thanks.
Remove the grants for a role to be able to SELECT/UPDATE/INSERT/DELETE against the table(s) involved
Grant EXECUTE on the role for stored procedures/functions/etc
Associate the role to database user(s) you want to secure
It won't stop an account that also has the ability to GRANT access, but it will stop the users associated to the role (assuming no other grants on a per user basis) from being able to execute queries outside of the stored procedure/functions/etc that exist.
There are only a couple ways to do this. OMG Ponies has the best answer: don't allow direct sql statements against your database and instead leverage the tools and security sql server can provide.
An alternative way would be to add an additional tier which all queries would have to go through. In short you'd pass all queries (SOA architecture) to a new app which would evaluate the query for passing on to sql server. I've seen exactly one company do this in reaction to sql injection issues their site had.
Of course, this is a horrible way of doing things because SQL injection is only one potential problem.
Beyond SQL Injection, you also have issues of what happens when the site itself is cracked. Once you can write a new page to a web server it becomes trivial to pass any query you want to the associated database server. This would easily bypass any code level thing you could put in place. And it would allow the attacker to just write select * from ... or truncate table ... Heck, an internal person could potentially just directly connect to the sql server using the sites credentials and run any query they wanted.
The point is, if you leverage the security built into sql server to prevent direct table access then you can control through stored procedures the full range of actions availble to anyone attempting to connect to the server.
And how do you want to check for that? Queries sometimes have constant values that would just as easy be added to the query. For instance, I have a database that is prepared to be multi lingual, but not all code is, so my query looks like this:
SELECT NAME FROM SOMETABLE WHERE ID = :ID AND LANGUAGEID = 1
The ID is a parameter, but the language id isn't. Should this query be blocked?
You ask to block queries that don't use named parameters. That can be easily enforced. Just block any query that doesn't specify any parameters. You can do this in your application layer. But it will be hard to block queries like the one above, where one value is a parameter and the other one isn't. You'll need to parse that query to detect it, and it will be hard too.
I don't think sql server has any built in features to do this.
I'm trying to log hibernate activity (only dml operations) to an sql script file.
My goal is to have a way to reconstruct the database from a given starting point to the current state by executing the generated script.
I can get the sql queries from log4j logs but they have more information than the raw sql queries and i would need to parse them and extract only the helpful statements.
So i'm looking for a programatic way, maybe by listening the persist/merge/delete operations and accessing the hibernate-generated sql statements.
I don't like to reinvent the wheel so, if anybody know a way for doing this i would appreciate it very much.
Thanks in advance
Generally the best way to do this is to just turn on logging on your SQL server. All the major RDBMSes support logging all the SQL statements that they run. This has the added advantage of catching things that happened outside of Hibernate.
You could also try to use NHProf which will intercept/record hibernate traffic to the database and dump it into an XML file. You might have to parse the file by hand, but all the information will be there.
You could also hook at the JDBC level directly and record the JDBC statements that are performed.
P6Spy is a great tool to inspect what's going on. It can log the queries, though I don't know if you can replay them as is.
I'm sure there are other such tool (or at worse you could try subclass the DataSource, Connection and PreparedStatement implementation of your choice to do that yourself).
Is there any way to confirm that a particular breach of security was done through SQL injection?
There is no easy way here, but if you have the enabled the SQL server you use to log every single sql statement, here is what I would do.
Normally, when I SQL inject somewhere, i use one of these as my always true statement for passing throgh the Where clause, after ending the former string.
1=1
0=0
both being used as :
blahblahblah' or 1=1 --
You would not use this clauses in everyday code. So if you spot one of these in your history, well, it is a high candidate. Test the sql history to find :
(space)(number)(optional spaces)(equal)(optional spaces)(same number)(space)
Keep in mind that is heuristical, and will not always work, but could be the only way to give a hint after it had happened . Also, if you are in doubt about SQL injection, you should check the code for string concatenation and use of parameters.
after the attack has already happened? no. there isn't.
you'll have to check all your sql serevr access point for potential risk.
tere are some tools you can use. Check here under SQL Injection tools section.
SQL injection can happen any time you pass a query back to the database.
SQL Injection
Use mod_security to log POST requests and install an Intrusion Detection System to log/stop suspicious activity from now on. Logging every SQL request is an overhead if you are just looking for the breach points.
There are open source alternatives for IDS these days. I use PHPIDS for all my PHP applications.
Only one reliable way is probably analysing the SQL log files. Those should be done by a DBA who can spot things quickly as the size of logs would be huge.
It is better to prevent those.
There are some tools for that but the best one is the brain of the developer.
Stick with one simple rule - always use parameters when generating SQL query.
Just do the code review and if you find string cocatenations - that is first and highly possible place for SQL Injection.
You can log all http requests and check the requested pages for GET/POST sql injection tryouts.