In Oracle: how can I tell if an SQL query will cause changes without executing it? - sql

I've got a string containing an SQL statement. I want to find out whether the query will modify data or database structure, or if it will only read data. Is there some way to do this?
More info: In our application we need to let the users enter SQL-queries, mainly as part of the applications report system. These SQL queries should be allowed to read whatever they like from the databse, but they shouldn't be allowed to modify anything. No updates, deletes insert, table drops, constraint removals etc.
As of now I only test whether the first word in the string is "select", but this is too constricting and too insecure.

You should grant only select privileges on your tables for the login used by the application to be sure.

Create a new user for that part of the application that only has select privileges. Bear in mind that you'll also need to create synonyms for all the tables/views that that "read-only" user will be able to view.
The "regular" part of your application will still be able to do other operations (insert, update, delete). Just the reporting will use the read-only user.
As Horacio suggests, it is also a good idea/practice to add "wrapper" views that only expose what you want to expose. Some sort of "public API". This can give you flexibility if you need to change the underlying tables and don't want to/can't change the reports to the new definitions of said tables. This might, however, be seen as a lot of "extra work".

I agree with others that the right thing to do is use a separate schema with limited access & privileges for those queries that should be read-only.
Another option, however, is to set the transaction read-only before executing the statement entered by the user (SET TRANSACTION READ ONLY).

Create VIEWS to expose the data to end users, this is worthy because of three things:
The end user doesn't know how really your database look like.
You may can provide a simpler way to extract some pieces of data.
You can create the view with a read-only constraint:
CREATE VIEW items (name, price, tax)
AS SELECT name, price, tax_rate
FROM item
WITH READ ONLY;

Something that has worked well for me in the past, but may not fit your situation:
Use stored procedures to implement an API for the application. All modifications are done via that API. The procedures exposed to the front end are all complete units of work, and those procedures are responsible for rights enforcement.
The users running the front end application are only allowed to call the API stored procedures and read data.
Since the exposed API does complete units of work that correspond to actions the user could take via the GUI, letting them run the procedures directly doesn't get them any additional ability, nor allow them to corrupt the database accidently.

SELECT * FROM table FOR UPDATE works even with only SELECT privilege, and can still cause a lot of damage. If you want to be safe, the read only transactions are better.

Related

GRANT Database Permissions for specific tables and the validity of this as a security practice?

my question is rather simple.
Can i grant permissions on a database table wise? something in the lines:
User Management has permission to select, update, insert and delete on table Projects
User Supervisor has permission to select, update, insert on table Projects
User Colaborator has permission to select on table Projects
If so, I could set up a system to create database users based on the levels of access of my application, much like the examples above.
Is it a valid mechanism to use this to secure a application?
is it worth on a real world application?
i've used PHP with Oracle and MySQL, but I'm look for a database/language agnostic answer, but any example would be useful.
pushing my luck a bit, what about per record permission granting?
also, what about table schemas, are they a more acceptable then table based permissions?
The main problem with using database security would be that you need separate connections for each user rather than being able to use a "service user" for the connection from your application server to your DB server. That would mean that you would no longer be able to use database connection pooling have to "connect" and "disconnect" from the database for every user request, which is not very efficient as connections are relatively expensive.
Having said that, there is good reason for using separate users in the database, such as DATA_USER (which the application server connects as) and DATA_OWNER (which owns all the tables but is used only for DB maintenance) and then only give DATA_USER the permissions that it needs to, e.g. only select on a lookup table. By separating DATA_USER and DATA_OWNER you can add an additional level of confidence that your application won't issue DDL commands (e.g. dropping a table).
Answer to part 1:
Yes as long as you handle the responses correctly.
Part 2:
It's not as good as implementating security in the application layer, as most applications will need flexibility in the solution (what if you want a user to get increased privledges, have to code in lots of alter/deny/grant scripts)
Part 3: (Speaking from purely MSSQL) Row-level permissions aren't possible. Create custom views for this purpose.

Ensure that a SQL query is READ-only

What would be the best way to ensure that a SQL query won't alter the data of a database?
In my scenario, you don't have access to the database layer and can only do this logic on the application layer.
Would you recommend using a gem, a ruby custom script?
You can manage the permissions of the users so that they have access for reading the database but they don't have access to alter the database (i.e. not able to insert, update and delete). If you are using mysql, for instance, you can easily do this in phpmyadmin or equivalent tool.
Update based on your change. Even if you only have access through the application you are still connected to the database as a user who has or does not have privileges to update, delete, insert or select and as such the only way to ensure no such queries are executed is to alter that user's permissions.
A simple but far from foolproof method is to employ a blacklist of words that cannot be in the query, such as insert, update, etc.
Alternatively, you could use a parser on the sql query that will provide you with the necessary information to derive whether or not to allow the query.
I would take option 1 only as a last resort or if your checking needs are relatively simple.
On the database layer, make sure that the user the Rails app is accessing the database as only has the access that you desire, perhaps only SELECT.
Sequel has support for read only slave databases with a writable master database. Read-only slaves handle SELECT queries, other queries are done by the master database.
Maybe you can just setup master database as nil?
Another approach could be using hooks (before_save) to prevent writing to the database.

Allow some SQL in public API?

I'm exposing a more or less public API that allows the user to query datasets from a database. Since the user will need to filter out specific datasets I'm tempted to accept the WHERE-part of the SELECT statement as an API parameter. Thus the user could perform queries as complex as she'd like without worrying about a cluttered API interface.
I'm aware of the fact that I would have to catch SQL-injection attempts.
Do you think that this would circumvent the purpose of an API wrapping a database too much or would you consider this a sane approach?
In general, I'd recommend against letting them embed actual sql in their requests
You can allow them to submit where conditions in their request pretty easily:
<where>
<condition "field"="name" "operator"="equal" "value"="Fred"/>
</where>
or something similar.
The value of doing this is muli-fold:
You parse each condition and make sure they're correct before running them
You can create 'fake' fields, such as "full_name" that may not exist.
You can limit the columns they can put conditions on
You can isolate the users from actual changes in your underlying database.
I think the last point is actually most important. The day will come when you'll need to make changes to the underlying schema of the database. Eventually, it will happen. At that point you'll appreciate having some 'translation' layer between what the users send in and the queries. It will allow you to isolate the users from actual changes in the underlying database.
The API should present an 'abstracted' version of the actual tables themselves that meet the users needs and isolate them from changes to the actual underlying database.
I would recommend limitting your users account by modifying the permissions to only allow the user to SELECT from tables. Don't allow updating, inserting, or deleting recordsets. Lock down the user as much as possibile, possibly at a table level.
If the WHERE clause is limited to only a few columns and the comparator is limited to >, = or < then perhaps you could just have the user pass in some extra parameters to represent columns and comparators. You then build the WHERE safely on your server side.
If this is too messy then by all means let them pass a full WHERE clause - it's not too hard to sanitise and if you combine that with running the query under a locked-down account (SELECT only), then any potential damage is limited.
Personally I would not want to allow users to be able to pass in SQL directly to my database, the risks are too great.
If you fail to catch all injection attempts you risk either data theft, someone just destroying your database or hijacking it for some other use that you really dont want.

How should i work in this scenario . Should I use Trigger or Leave on User to manage

I am creating an application in which i am using stored procedure where i m implementing my logic.
Now what i need to know is that- i want my database not to contain any invalid entry, for this purpose should i create triggers, for implementing my data validation logic such that when FailPasswordAttemptCount is changed to some value then should i make changes in corresponding column IsLocked accordingly thru triggers or leave it on dba to manage.
eg
if FailPassowrdAttemptCount > 3
IsCaptchaActivated=True
if FailPasswordAttemptCount>6
IsLocked=true
now if a dba changes the value of FailPasswordAttemptCount to 4 without changing IsCaptchaActivated to true then this will make an invalid entry for my frontend.
SO should i manage it thru triggers or should i left it over dba to make correct entry.
Although this type of entry is not possible thru frontend but in case any1 having privilages to access database, changes directly thru database.
For this should i leave it on user or should i manage thru triggers.
I want to make my database to remain consistent in all circumstances.
I'd make the following:
Put the data validation logic into a stored procedure
Made the stored procedure the only way the application interacts with the table
Put the code you want into the stored procedure.
Trigger-based programming paradigma grows too hard to code and maintain as the business logic complexity of your application increases.
However, if you are absolutely sure you will only have the simple logic like this, it is OK to put it into a trigger since this will require minimal changes in the ways the application interacts with the database.
I wouldn't use a trigger for something like this. Triggers are obscure and can be hard to debug for the developer. Use your tables and stored procedures to deal with the issue. Use triggers for when you don't have an alternative.
I would use a combination of both. I will try to restrict data as far as possible. And will fire trigger, so that no one can insert any invalid entry.
For this type of situation, I would probably not use a trigger, just for the situation you describe. Though I would wonder why you have dba's manually altering data in a field that closely tied to the security of your app.
I would implement this in the application logic. When calling the login sproc you can return both whether it succeeded as well as the number of failed password attempts and if captcha is needed. Regardless of if the DBA changes the 3 to a 4, your code will see the 4, ignore the result of the validation and present the user with a captcha. If you're worried about DBA's modifying the code directly you can also check the APP_NAME() function/variable to see what program is trying to modify the data. Its something to be very careful with but so is DBAs modifying fields directly.

What security benefits are provided by using stored procedures to access data?

I have seen some guidance which recommends that you secure a database by layering all data access through stored procedures.
I know that for SQL Server, you can secure tables, and even columns against CRUD operations.
For example:
--// Logged in as 'sa'
USE AdventureWorks;
GRANT SELECT ON Person.Address(AddressID, AddressLine1) to Matt;
GRANT UPDATE ON Person.Address(AddressLine1) to Matt;
--// Logged in as 'Matt'
SELECT * from Person.Address; --// Fail
SELECT AddressID, AddressLine1 from Person.Address; --// Succeed
UPDATE Person.Address SET AddressLine1 = '#____ 2700 Production Way'
WHERE AddressID = 497; --// Succeed
Given that you can secure tables and even columns against CRUD operations, how does using a stored procedure provide additional security, or management of security?
Because by limiting all access to those stored procs you have established a defined interface to the database, through which all access must occur... Since you will have DENY'd Direct select, insert, update, and delete operations against the tables and views, noone can directly write sql of their own design that does whatever they want to... If you want to limit inserts into the employee table where the employee is assigned to more than three projects to to only those employees that have a score greater than 85 on a proficiency test, then you can write that constraint intoi the SaveEmployee sproc, and have it throw an exception to any client code that attempts to do that...
Sure you COULD do the same thing using client-side code, but using sProcs makes the process easier to design and manage, cause it's all in one place, and ALL applications that attempt to access this database system HAVE to conform to whatever constraints and/or security provisions you define in the SProcs... No rogue developer writing a new separate client app that hits the database can ignore or work-around a constraint or security provision in a SProc if that SProc s the ONLY WAY to insert or update a record...
You might not want to give Matt carte-blanc to update certain tables or columns directly. What if Matt decided to do this:
UPDATE Person.Address SET AddressLine1 = NULL
Whoops. Matt forgot the WHERE clause and just hosed your database. Or maybe Matt just got pissed at his boss and has decided to quit at the end of the day. Or maybe Matt's password isn't as secure as it should have been and now a hacker has it.
This is just one simple example. Control over tables and columns could become much more complex and might be untenable through anything other than stored procedures.
Stored procedures provide additional security by allowing users to perform CRUD operations (insert, update, delete) but only in a limited fashion. For example allowing user Matt to update the address of some rows but not others.
It allows you to add data checks to make sure that the data inserted is valid data, not random garbage. For most things you can use constraints and or triggers to do some of this work, but there are limitations. Stored procedures enhance security by ensuring that operations being performed are allowed by the user.
It's easier to track changes to the database though a single point of access, controlled by your applications, rather than through any number of interfaces. And the procedure can update an audit log.
In SQL Server you do not have to grant any direct access to tables if you properly use stored procs (that means no dynamic SQl). This means your users can only do thoses things defined by the procs. If you have any financial data at all in your database or data of a sensitive nature, only the fewest possible number of people (generally only dbas) should have direct access to the tables. This seriously reduces the risk of fraud or disgruntled employees trashing your business critical data or employees stealing personal inmformation to commit identity theft. In accounting terms this is a necessary internal control and developer convenience or personal desires to do everything dynamically from the user interface should be trumped by the insecurity of of the data. Unfortunately in all too few companies, it is not. Most developers seem to only worry about outside threats to their data, but internal ones are often far more critical.
If you restrict the user at the table level and then the user fires off a query to do a legititmate insert, it won't happen. If you give them the rights to do inserts, then they can do any adhoc insert they want and aren't just limited to the ones coming from the user interface. With stored procs, they can only do the things specifically defined by the proc.
In most (all?) RDBMS's you can 'GRANT' access on specific tables to specific users. A stored procedure can run as a different user, one with greater access. But the Stored procedure is not the same as giving access to the whole table, rather it could first check some things and only return rows that match your particular security concerns.
You might be able to do similar checks with a view but stored procedures are usually much more flexible since they can run almost any SQL - compare the results and decide what rows to return.
The stored procedure is better because the security on the stored procedure (IIRC) will trump security on the tables/columns.
For single-table access, that's not a big deal. However, if you have an operation that involves multiple columns on multiple tables, having one access/deny flag for a table/column might not work for all situations.
However, a stored procedure can perform the composite operation and you can set the security appropriately on that.
Simply put, it lets you define security functionally rather than structurally. In other words, it restricts what a user is allowed to do (with a greater degree of granularity) rather than what database objects are accessible (at very coarse granularity.)
Note that we're speaking of "security controlled by the DBA", rather than by the site or system administrator or software module, all of which are useful and part of the overall security infrastructure.
The first benefit, discussed at length here, is better control of permissions - users can be limited to specific rows, not just per column (which btw is heck to manage in a large system); SPs can enforce business logic and transactional logic; data might be only retrieved dependant on other data (e.g. a join); updates might be limited to single rows at a time; etc.
Second, this can provide an additional layer of protection against SQL Injection (albeit its not complete and automatic). While this may be broken be dynamic SQL inside the SP, or by bad concatenation calls, the SP does enforce parameter types and whatnot, separating code from data.
Third, it comes down to control, at the development phase - typically you'd have trained DBAs writing the SPs, as opposed to programmers (who are trained in code...)
This is, not to mention, non-security benefits, such as better performance.
In stored procedures, you can add logic controls. You can return a error code if something is not right instead of update table data directly.
For example, you have a feedback system. Feedback can only be submitted after the administrat started the feedback campaign. It is simply updating a flag in some table.
Then when user comes to submit feedback, SP can check if the flag is set.
Select #IsFeedbackDefined = IsFeedbackDefined From sometable where ID = #ID
IF #IsFeedbackDefined is Null or #IsFeedbackDefined = false
Begin
Return -2 --can not submit feedback
End