How to avoid SQL injection and other security failure in JavaFX desktop application - sql

Is there any method to avoid SQL injection and other security failure in JavaFX desktop application? If yes, how can I do it?

SQL Injection attacks are related to malicious statements deliberately sent by the end user to the database, while JavaFX is the front-end from a user's point of view.
That said, let's assume you have a login screen to input user and password. Could you prevent the user to type one of the following sentences instead of their real user name?
DROP TABLE Users; --or
DELETE FROM Users WHERE 1=1;
You could validate the text looking for certain keywords like DROP, INSERT, UPDATE or DELETE. But is it worth? Maybe it does, depending on how probably is the users will try to go ahead with this kind of attacks.
However the best way to mitigate and frustrate SQL injection begins from the connection itself. Tipically you'll want to connect to the database with users that have the less necessary privileges to operate. A common practice is to create a dedicate user to do the login for example, with read-only access to the Users table and maybe INSERT and UPDATE granted to a Sessions table (if you are interested in keep a sessions log of course):
CREATE USER 'login_user'#'%' IDENTIFIED BY 'password';
GRANT USAGE ON MyDataBase.* TO 'login_user'#'%';
GRANT SELECT ON Users TO 'login_user'#'%';
GRANT INSERT, UPDATE ON Sessions TO 'login_user'#'%';
Note: the snippet is based on MySQL but the same concept applies to other RDBMS as well.
In this scenario, if the end user succeeds in sending one of the above sentences to the database, the db user which was established the connection wont' have enough privileges to perform none of those sentences and will cause an SQL exception. The same applies to other entities as well, just provide a db user with the less privileges to operate with sensistive data.
In addition, JDBC provides PreparedStatement interface which is intended to avoid SQL injection by using placeholders to build the statements. For example:
String sql = "SELECT * FROM Users WHERE username = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, userName);
The userName parameter will be wrapped into literals before sent the statement to the database so if the user types one of the above malicious sentences they won't have any effect. Plus, if you want to execute more than one sentence you have to use addBatch() and executeBatch() which is under developer's control, making it even safer.

Related

How to prevent SQL injection attack when a sql query is passed in from the UI

I have a Java application that does a POST with the sql query that is typed in the UI and is executed using JDBC. Since the query is user defined, I'm unable to find a way to prevent the SQL injection issue. For instance if this is the query the user issues :
select * from test_table where id=123
a POST is done with this string to the servlet and this is executed as a query. Is there anyway to get around this since there is no restriction on what user can send in?
Thanks
Technically if the user is allowed to write the entire query, it's not an injection attack risk, it's simply an attack risk
Run the query using a database user that has permission only to carry out the types of operations you deem acceptable on the tables you're willing to give access to.
For example, only permit SELECT on tableX, tableY and tableZ. No DML, no DDL and no selecting from any other table
If your dbms of choice doesn't allow fine grained control in this way then instead execute a regular batch script that creates another database containing only a few tables. Permit your users to query this new db. If it does get wrecked it will soon be dropped and replaced by a working one with updated data, by the script. This is also beneficial if placed on another server, it stops your live system from being innocently DOSed by a user executing a duff query that takes up all resource on the server
SQL injection would be passing select * from test_table where id=123 in place of a parameter.
Not sure exactly what information you are letting the application use, but I would suggest granting access only to a specific schema. That would provide a consistent security model.
As others have suggested, this is not SQL injection - I call this a "designed in" SQL injection. How you deal with it depends on the use case:
Design a separate interface that does not require the full SQL statement
As Caius suggested, if you can limit the privs in the DB account to only do what the user can do, that would limit the damage
If this is an administrative interface, you may want to limit the usage of this interface to "trusted" users. If you go that route, you want to be very careful to document that users with this privilege have full access to the database, and provide an auditing mechanism to make sure that that list of users is well known.
It is not realistically possible to limit the SQL statement through validation - its a powerful language, especially in the context of modern databases.
See also this related question
Is there anyway to get around this since there is no restriction on what user can send in?
I'm not sure what you mean by "get around." Is it not the design of this application to allow users to run any query?
If you want to prevent them from running unauthorized queries, then you'll have to implement some Java code in the servlet to check the query and decide whether it's one they're authorized to run.
Some people do this by whitelisting a specific set of known queries. Just match the user's input query against the whitelist.
If they can run a given query with a variety of different constant values, then replace constant values with a ? in both the whitelisted form and in a copy of the user's input SQL query.
If they can run a variety of different queries, like with optional clauses and stuff, so that it's impossible to make a whitelist of finite length, then you'll have to implement a SQL parser in your Java servlet and some kind of business rule engine to decide if their query is authorized before you run it against the real database.
At this point, it seems easier to change the application front-end so that users are not allowed to submit arbitrary SQL queries!

Is it possible to change a database by SQL SELECT statement?

We want to allow to an administrator (only) to execute an SQL SELECT statement via Web UI.
Please note that the administrator is allowed to view all information in a database.
What are security risks with this approach?
Is it possible to change somehow a database by SQL SELECT statement (any record or table)?
added
RDBMS is PostgreSQL
We want to allow to an administrator (only) to execute an SQL SELECT statement via Web UI. Please note that the administrator is allowed to view all information in a database.
What are security risks with this approach? Is it possible to change somehow a database by SQL SELECT statement (any record or table)?
Well, how do you propose to let them execute SELECT statements? PostgreSQL doesn't have user-level statement privileges, it has privileges on individual database objects.
In theory you can absolutely modify the database with SELECT. Just look at PostgreSQL's function list. Not to mention the user-defined functions. The most obvious case is of course nextval, which advances a sequence, or setval which sets a sequence's position.
However, everything requires rights on the associated database objects. If you only GRANT the SELECT right on a table (or some subset of the column's tables) then the user won't be able to modify the data in that table directly. Nor does PostgreSQL provide functions to bypass that restriction built-in. So simply creating a user with only SELECT rights to some tables and USAGE rights on the schemas they're in should be fine.
There are some important caveats though. SECURITY DEFINER user defined functions can do anything the defining user can do so if you have SECURITY DEFINER user defined functions that weren't carefully written you might have opened security holes. The same is true of user-defined functions written in C - so consider your extensions carefully. Finally, you need to be extremely careful about any functions written in "untrusted" languages like plpython, plperl, etc (as opposed to plperlu which is sandboxed) as these must be implemented carefully to make sure the calling user can't trick them into doing things they weren't supposed to do.
If you plan to give a user direct access to write raw SQL you have to be more careful about securing your DB. Don't GRANT rights to public, and REVOKE them where they're granted by default. Check security definer functions to make sure they have a SET search_path option defined. Etc. It's generally safe, but only if you're careful.

How can I allow SQL Injection safely

So I wanted to know if there is an acceptable method to Allow SQL Injection.
Example:
Limit permissions on the table(s)/database(s)
Why you ask?
My employer wanted to devise a way to test the skills of applicants, one suggestion was to allow resume submissions via SQL Injection.
Any thoughts? suggestions?
You could use roles. Create a role for the web application (or whatever) that is used to connect to the database. Limit this role to only permit INSERT and access to necessary tables for applying. Applicants with access to your database through the application could then only use SQL injections to add their resume.
It may be possible for someone more talented in SQL to use injections in a way that increases the role's permission. But I think if the role had limited access to only specific tables and didn't have CREATE or GRANT privileges, the user wouldn't be able to create new roles.
Here is some information on roles to get you started:
Adding Roles to MySQL with MySQL Workbench
Creating Roles in PostgreSQL
GRANT command - used to add privileges to users on table, database, etc. This page is for PostgreSQL, but MySQL is very similar (see this SO answer)
Given that the reason behind this is to test people's ability, create a database with data you can afford to lose. Set up a form that posts to a coldfusion or php or java or .net or some other type of page which connects to that database.
On the form, put a textarea and submit button. On the form target page, log what they put in the textarea. Compare the log to the database to see how it turned out.
Then test to your heart's delight.

User-generated SQL Query

I'm developing a data warehouse using Ruby on Rails and I should allow the user to perform arbitrary SELECT queries on the application database.
I know this is what you usually SHOULDN'T do, but it's an interface my client actually needs (I can't think of all the possible queries the user might want to do and translate them to ActiveRecord queries). There could be complex joins and sub-queries and so on.
I'd rather do this (integrate it to my app) than let them access the DB via pgAdmin (I'm using postgresql).
My question is: what is the safest way of doing this? I should be able to escape anything like INSERT, UPDATE, DROP TABLE, etc...
I'm thinking of getting the query string and sanitizing these "dangerous" words and then using ActiveRecord::Base.connection.execute(sanitized_sql_string).
Is this a reasonable approach?
The safest way would be to let Postgres handle this security for you. Create a new user:
CREATE USER Reader; -- Your Rails app should logon with this user
Then, explicitly grant SELECT permissions on the objects you want them to be able to query:
GRANT INSERT ON TableFoo TO Reader;
GRANT INSERT ON TableBar TO Reader;
Then, they'll be able to run arbitrary SELECT queries from these two tables, but if they try an INSERT, they'll get Permission denied. You can then trap those security exceptions and handle them in your UI appropriately.
Create the application then create the database.
After this, in your database configuration (database.yml), connect to the database with some non-default user, say lame_user. Create this lame_user on your RDBMS, in your case PostgreSQL, and grant him only SELECT permissions on all of your tables.
You will now have the user postgres and the lame_user that can access your database, but only postgres can do all the stuff.
If the user tries to do anything besides SELECT's, an error will occur.
Resuming: Make this application constraint a database thing. It will be easier.

Disable all queries in SQL Server that don't use named parameters?

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.