What is the security risk if Ad Hoc Distributed Queries are enabled? - sql

Before I ask my boss to enable Ad-Hoc queries, I want to know what I'm asking for.
Every once in a while (at least once a year, but not more than once a month), we get an excel sheet that has information that we need to put in the database. I'd like to write a stored procedure that takes the path to the spreadsheet as a parameter and does the necessary processing, but when I try to use OPENROWSET, I get this error:
Ad hoc access to OLE DB provider 'Microsoft.Jet.OLEDB.4.0' has been denied. You must access this provider through a linked server.
I've done some looking, and it seems that I have two choices:
Add a linked server, which is undesirable because it sounds like I would need to put the excel sheet directly on the machine that is running SQL Server. I would like anyone on the team to be able to run this process, but not everyone should necessarily have access to the server machine.
Allow Ad-hoc access to the database. This seems more desirable, but I want to know why Microsoft disables this functionality to begin with before I go asking permission to poke holes in our security.
So, does anyone know what the actual security risk is here, or is it just Microsoft being paranoid?

Related

SQL - is it bad practice to give Read-Only access to the entire company?

I work in my companies small IT department. I have been creating automation via VBA in Excel to pull data from SQL and put it into Excel, then dynamically format and summarize the data. The issue I am running into is the IT department does not want to give anyone outside the IT department SQL Read-Only Access. They view SQL as a privilege not a right...even if it is only Read-Only. They claim security reasons.
Just to be clear, we are NOT installing SQL on these peoples' computers nor do they have the technical understanding on how to write queries. Also, they can already view all the information on the front-end website.
I currently have to specify which database and which tables they can have access to and it takes about 1-2 weeks to give them access (they drag their feet doing the requests).
I am not trying to vent, I am actually wondering do they have a legit concern about security and is this actually a best practice on their part?
The worst thing that could happen is a user knows just enough to connect MS Access to the database, write some poor queries, and grind everything to a halt. You should always have non-IT users access data in a safe, structured way. Especially if this database is a transactional one, and not a reporting database.
Sure, they can access all the data per business process. So then, create a nice, safe query to read all the data and dump it to Excel - if that's what the users want.
Otherwise, IT-created queries - preferably in Stored Procedures - should be reading the data and presenting it to the users.
So it's not a security issue per se. It's more an issue of "we don't want non-IT users getting crafty and bringing down the database with poorly written queries."
I believe the connection properties to the SQL server is embedded in your VBA code, as long as the code is not visible to the user then there is no way they can query the SQL server directly.
Sounds like you need an SQL read only service account which you can use for Query connections. Create an Excel data connection that has the security details to connect to SQL, then your VBA hooks into that data connection.

SQL Injection when using native database logins/users

When developing an application where users connect with their native database logins, I don't need to care about SQL injection right? The reason being the users can execute any SQL they want anyway. (There are places where admins execute CREATE LOGIN and CREATE USER statements and these have to be dynamically built.) I'm talking about a native Windows application on the LAN.
Well, SQL injection is a possibility to execute SQL, so with the SQL shell access, everything required for "SQL injection" is already authorized. However you still need to care if users run as non administrators, probably being restricted which tables they can access, and your system sends some additional SQL commands while logged in with higher rights (create user, etc). Use prepared statements for such a code.
If you mean that you are building a web application, and using users' database credentials to connect to the database, yes, you do need to worry about SQL injection.
Most databases restrict permissions based on objects - tables, views, stored procedures etc. So, a user logged in as "Bob" might have access to table "sales", but not table "payments".
The database does not restrict access to rows in tables (for instance). So, a user connected as "Bob" who can exploit a SQL injection bug in your code can delete every record in the "sales" table. You probably don't want that.
If user "Bob" also has direct SQL access, they could, of course, simply run that statement at a SQL command line - but usually, web applications are available where direct SQL access is not. Your web app may be put on the intranet to begin with, but you can't guarantee that won't be opened up in the future.
Given how easy it is to prevent SQL injection attacks when you're building the app, and what a pain it is to fix them later on, I see no real reason not to prevent them in the first place.
As a matter of fact, "SQL injection" is a common misconception.
Being unable to properly format their queries, folks invented an "sql injection" thing as an excuse.
While properly formatted query will serve 2 purposes at once:
it will always be syntactically correct, no matter what data sent in.
as a side effect it would be invulnerable to that notorious "SQL injection" thing.
I doubt you want your queries to fail because of some unexpected symbol. So, no matter of some "injection", you have to properly format it. But once formatted, there will be no injection anyway. So, you have to concern about format, not injections.
I also have a feeling that letting users to login with database credentials is not quite a good idea.

Creating SQL Windows login for External Domain

Problem
Is it somehow possible to create a Windows Authentication login for a SQL database without performing a check for the user at creation time?
Example
Consider ServerA that exists in our DomainA, and ServerB that exists in the customer's DomainB. Being separate companies, DomainA and DomainB never share resources. But, if we backup from ServerB and restore to ServerA, we are able to see the existing SQL logins for users from DomainB, and even modify and code against these logins. This is good, because we are able to develop the database schema on ServerA and then publish to ServerB.
But, if I want to add a new user for this database, and am working on ServerA in DomainA, the following command produces an error:
CREATE USER [DomainB\User];
Windows NT user or group 'DomainB\User' not found. Check the name again. (Microsoft SQL Server, Error: 15401)
This is bad, because we're no longer able to develop on ServerA using the same schema as ServerB.
Backstory
I'm attempting to bring our database-driven application's database schema into source control using a Visual Studio 2010 Database Project. It's important to me to make this work well enough to convince the boss not to continue using 60-GB database backups in a zip file as a means of 'Version Control' (especially since this is just for schema, and not a backup routine). VS2010 DB Projects use scripting to create/modify databases, and so they can't create WinNT users for an unknown domain. In order to get the boss's buy-off, we're going to have to be able to match the capabilities of restoring a backup, and that means being able to re-create users for domains that we don't have access to.
Using SQL Server 2008 in my case.
Note - DBProjects are best suited to managing and versioning your SCHEMA, not your data.
If you want to keep rolling backups of your SQL databases as a whole, then I'd recommend a decent backup strategy.
If you want to better manage your databases' evolving schemas, then using DBProjects may well be your best bet.
FWIW, if you reverse-engineer a DB into a DBProj, you could then run a script to replace DomainB\known-user with DomainA\known-user prior to deploying within DomainA, no?
No, because SQL needs to know the windows SID (ugly GUID) of the user at the time it's created.
Note that you can, however create a SQL or Windows User with the same name and password as your remote SQL, Machine, or Domain user, and it will be able to log in.

How to hide all databases I am not authorised to use in Sql Server 2005 Management Studio?

I have to access some customers databases being hosted in a shared environment. There are numerous databases being hosted on any given customers instance. So everytime I access a database I have to scroll and search.
I would like to be able to configure Management Studio to just go directly to the database I want to work with for a given connection and hide all others on that connection/instance. But i still want to be able to see databases on other instances i might be working with, i.e. local using the same Object Explorer.
If that not possible is there any reason why the web hosting provider would grant their customers the VIEW ANY DATABASE permission? Im assuming thats why I can see all the other dbs?
If i cant configure Management studio to do what i want as per (1) then I was going to email the provider and ask that they prevent me from seeing them from the "server" end. Would this be an easy thing for them to do? If they REVOKE the VIEW ANY DATABASE permission then that should solve my "problem" right? But would it create any others?
You will require access to the master db to effect the outcome you want. There are no options to configure Sql Server management Studio (SSMS) to do what you want.
So (1) is out.
(2) however is a go so long as your service provider play alongs. You are right they will have to
DENY VIEW ANY DATABASE TO youruseracount
which will require access to the master db. But before they do this they will have to set youruseraccount as the owner of your database.
sp_changedbowner 'youruseraccount'
The side affect of all of this is
a. You wont be able to see any other databases in the instance which is what you want.
b. Only one user will be able to use SSMS to admininster your database with the 'View Only My Db' list. This is because only one user can be the Database Owner.
..
Richard
2 articles describe it (no point if I copy/paste, really)
One and Two

Best practice on users/roles on SQL Server for a web application

I searched online a bit and couldn't find anything that really nailed the spot or covered the bases how to go about setting up users/roles on a database.
Basically, there would be a user that would be used to access the database from the application (web application in this case) that will need access to database for the regular database operations (select, insert, update, delete) and executing stored procedures (with exec to run stored procedures within other stored procedures/UDFs).
Then, we would also have a user that would be main admin (this is simple enough).
I currently have a development environment where we don't really manage the security too well in my opinion (application uses a user with db_owner role, though it is an intranet application). Even though it is an intranet application, we still have security in mind and would like to see what are some of the ways developers set up the users/roles for this type of environment.
EDIT: Web application and SQL Server reside on separate machines.
EDIT: Forgot to mention that an ORM is used that would need direct read/write access.
Question:
What are the "best practices" on setting up the user for application access? What roles would apply and what are some of the catches?
First, I tend to encapsulate permissions in database roles rather than attach them to single user principals. The big win here is roles are part of your database, so you can completely script security then tell the deployment types to "add a user and add him to this role" and they aren't fighting SQL permission boogeymen. Furthermore, this keeps things clean enough that you can avoid developing in db_owner mode and feel alot better about yourself--as well as practice like you play and generally avoid any issues.
Insofar as applying permissions for that role, I tend to cast the net wider these days, especially if one is using ORMs and handling security through the application. In T-SQL terms, it looks like this:
GRANT SELECT, UPDATE, INSERT, DELETE, EXECUTE on SCHEMA::DBO to [My DB Role]
This might seem a bit scary at first, but it really isn't -- that role can't do anything other than manipulate data. No access to extended procs or system procs or granting user access, etc. The other big advantage is that changing the schema--like adding a table or a procedure--requires no further security work so long as you remain within that schema.
Another thing to take into consideration for SQL 2005+ is to use database schemas to secure groups of objects. Now, the big trick here is that many ORMs and migration tools don't like them, but if you render the default schema [dbo] to the app, you can use alternative schemas for special secured stuff. Eg--create an ADMIN schema for special, brutal database cleanup procedures that should be manually run by admins. Or even a separate schema for a special, highly secured part of the application that needs more granular DB permissions.
Insofar as wiring in users where you have separate boxes, even without a domain you can use Windows authentication (in Sql Server terms integrated authentication). Just make a user with the same credentials (user/pass combo) on both boxes. Setup an app domain to run as that user on the web box and setup a Sql Server user backed by that principal on the sql box and profit. That said, using the database roles can pretty much divorce you from this decision as the deployment types should be able to handle creating sql users and modifying connection strings as required.
For a long time the SQL Server guidelines for application access to the database were to isolate access to data into stored procedures, group procedures into a schema and grant execute on the schema to the principal used by the application. Ownership chaining would guarantee data access to the procedure callers. The access can be reviewed by inspecting the stored procedures. This is a simple model, easy to understand, design, deploy and manage. Use of stored procedure can leverage code signing, the most granular and powerfull access control method, and the only one that is tamper evident (signature is lost if procedure is altered).
The problem is that every bit of technology comming out from the Visual Studio designers flies in the face of this recommendation. Developers are presented with models that are just hard to use exclusively with stored procedures. Developers love to design their class models first and generate the table structure from the logical model. The procedure based guidelines reuire the procedures to exists first, before the first line of the application is written, and this is actually problematic in development due to the iterative way of modern development. This is not unsolvable, as long as the team leadership is aware of the issue and addresses it (ie. have the procedures ready, even as mocks, when the dev cycle starts).
Create a user 'webuser' that the web application uses.
Only grant stored proc execute permissions to this user. Do not allow direct table read/write. If you need to read something from a table, write a proc. If you need to write data, write another proc.
This way everything is kept nice and simple. One app user, with only the relevant permissions. If security is compromised, then all the intruder can do is run the procs.