We have audit table in our database.
Records to this table are done using triggers.
Currently, there is nothing that prevents user to log on to database server, open table from management studio and change data in audit table.
What are possible mechanisms that can prevent (or at least detect) cases of audit data tampering?
I'm thinking of adding one column in audit table which should contain some hash calculated based on values that are entered in that row. However, since audit is done using trigger, malicious user could open any trigger and see the logic by which this hash is calculated.
EDIT:
I was not clear enough. Application user does not have access to database. I was referring to some user like DB admin, with appropriate rights on database. Still, if this DB admin logins and has rights to temper with audit table, I would like to have some mechanism to detect this tampering at least.
Nothing can prevent someone accessing your database via SQL manager from changing the contents. You can make it tamper evident though.
Basically you need to use HMACs which are keyed hashes. Unfortunately this leads you to requiring key management to ensure the key stays secret which may not be possible in triggers. We use a cryptographic service to provide the key management but this is accessed from code.
You also need to think about a users ability to delete a record rather than change its contents. We ended up with two HMACs, one calculated using the contents of the record (to make changes to a record evident), the second using the current records HMAC and the HMAC from the previous line to make any line deletion tamper evident.
Then you need to worry about deleting the first or last x records. For this we use a trailer and header record which always have the same contents, if those aren't present then the top or the bottom of the table has been deleted. The combined HMAC of the header uses the record after it rather than the record before (as there is no record before).
And, of course, if you are going to be deleting old records to manage the amount of data you store you'll need a mechanism to add a new header record after the deletion.
Here are some possibilities:
You can't prevent or detect tampering by somebody with sysadmin (sa) permissions. If you don't trust your system administrator, you probably have worse problems than this specific one.
It's difficult to prevent or detect tampering by a domain or local administrator. Such a person can restart SQL Server in single-user mode and gain access as a sysadmin using SQL.
To detect tampering by the database owner (dbo), you could use Server Audit in SQL Server 2008 or a server-side SQL Trace in earlier versions of SQL Server.
You can prevent tampering by other users by restricting their permissions to the relevant triggers and audit tables.
you could enable Change Tracking so you have kind of "Audit on the audit table".
if your infrastructure is properly managed I guess users do not have sa rights and they use Management Studio to see the database logging in with their windows account, in this case you can set security on that audit table, only sa and other administrative accounts will be able to change content but not normal users/developer accounts.
Hope this helps.
The problem you're describing may indicate a more serious problem in the architecture of your system.
Usually, users shouldn't even have direct access to the machines running the database.
You may want to consider an architecture where the database machine is separated from your business logic machines, and are accessible only to them.
If your users decide to try to access your servers not through your clients, then all they should be able to do is reach well defined web services that you decided to expose.
There's no reason that a user should be able to access a DB machine, or to have the credentials of an account that is allowed to write to the database. You seem to be worried about tampering with audit information. What's to stop a malicious user from deleting tables or tampering with functional data?
Separate the audit data into its own schema and then set permissions such that the users you're concerned about don't have access to that schema.
Use an entirely separate database which could even be on a different machine.
I often see some type of publish/subscribe model used to publish audit data from a relational database and then asynchronously write that audit data to the audit store.
Perhaps you could have your triggers write audit data to a queue. Then you could have a scheduled job that runs every few minutes to take audit data from the queue and write it to your audit store.
Related
I have a large subset of WordPress users in a MySQL database who I want to migrate to Identity Server 4/5.
While I could easily select the data and insert into the ASPNetUsers table, my concern is:
I'm bypassing the controlling application (Identity Server)
Also there appears to be, two cryptographic fields in ASPNetUsers table (SecurityStamp
and ConcurrencyStamp) which I don't know how to generate data for. Not populating them feels like it could lead to interesting side-effects.
What is the best practice in importing a large subset of users programmatically into Identity Server?
Those 2 values just need to be random and in the correct format and don't in themselves hold any meaning. They're just used to check if the DB record has changed since it was loaded.
The main thing to worry about is migration of password hashes. We solved this by having a back channel call to the source system to validate the password the first time the user signs in and then updated the local PasswordHash once we'd verified the provided password was valid.
I am creating an application to be accessed by multiple clients, but
each customer will have a different database, only access the
same application in IIS, I'm using DDD, C # and MvC3 and Entity Framework 4.1 CF. Does anyone have any example or an idea of how best to configure the connection string
specific to each client?
First, you need to identify whether it's a database per client (machine?), user identity authenticating, or some other identifier. For example, if it's per account, then two machines may be able to authenticate as that account and get the same storage.
Once you have that identifier, you'll need a master table somewhere with a map of account to database connection string. You'll probably also want to cache that table in memory to avoid two db roundtrips on every request.
That global configuration information is typically stored in a database. You could go as simple as a file but that would cause problems if you ever wanted to scale out your front end servers, so common storage is best.
Simple and contrived example:
C# desktop application talks to SQL Server database. All orders exist in Orders table.
Application views, creates and amends orders. In this example a user can only amend their own orders.
Concerns:
Storage of connection string if using dedicated sql credentials.
Even if user credentials are used, application security could be bypassed by connecting directly through Excel or Access.
Solutions:
Provide access to SQL through web service/middleware only. Good, but not necessarily viable in this case.
Encrypt connection string in application somewhere. Not hugely secure, security through obscurity.
Secure database by granting access to specific stored procedures, views, etc and no access to actual tables. SP's and views take into account the user's rights/credentials. Pretty awful. Ok for simple examples (Select where user , becomes complicated once you introduce users in different groups, manager relationships, etc.
Alternatives:
How would you approach this?
Thanks
Even if user credentials are used, application security could be
bypassed by connecting directly through Excel or Access
what do you mean? you should not allow users to connect to SQL Server directly or with Excel or Access. They should NOT know the sa or other password.
After this, surely you could encrypt some sections of your app,config so that nobody can see its content.
I would really have the logic that a user can only modify his/her own Orders at the application level. Could be done also in the stored procedures I guess but it depends and more details should be known about this to suggest the best or most appropriate approach.
Use windows authentication instead of sql authentication.
To allow users to see only their data you can create view and filter data based on the currently logged in user by using SYSTEM_USER to get the data for the current user only and deny select permission on the table itself.
You can't do row level security in SQL Server (well you can, but it's not straightforward). So your only choice to be totally secure is to go through a data-layer which controls access. You can store your credentials encrypted, but that's not totally secure, as you say. It depends what you need.
Well in our application we handle we store the connection string encrypted in a file.
So the user has no direct access to this file.
We also use sql connection only to our database and grant the user for this only.
If you use Windows Credentials to access it and want to prevent any manipulation you can disallow write access to table.
For reading the data you can build queries or access the tables.
For writing/adding/manipulating data you can create stored procedures. One of the parameter is the username. Inside the procedure you build your bussiness logic, impersonate to a user that has write access to finally write/update the data.
There you have your "layer" inside the SQL server.
But I wouldnt suggest to go this way :) It is possible but to many business logic inside the database imho. So the safest way is to find a good encryption class in your language, use sql auth only and store those data inside your code.
Many desktop applications use SQL tables to manage their users permissions and roles. In fact they restrict access to some parts of application in their application code. It means they need a constant connection string to SQL server with maximum permissions.
My target is C# 2010, Sql Server 2005 or 2008.
What if with any reason someone find that connection string ?(Network tracing, Software hacking, Fired Employee or ...), He can change everything with just Managemenst Studio and you can't understand which client did it. If you want to change connectionstring. You must do it in many clients and in a bad design you need to recompile application.
So i want to know is it good idea to use real SQL login instead of username and password in tables ? make connection string for each user by SQL Logins ?
In this way there is no afraid to loose connection string. Also in SQL codes you can use GetUser() function to indicate which user really runed the query ?
But maybe the managing permission is difficult with this way because there is no simple table to manage permissions and users.
In one long sentence. I want to know What is the best way for authenticating desktop application users in a way that managing permission can be done and also sql server can log user activity ?
Whenever possible, use Windows Authentication.
Define Roles. Add Groups to Roles. Add Users to Groups (as per usual Windows way of managing file system permissions).
Choosing an Authentication Mode
See: Application Roles
You can encrypt sensitive sections of your app.config file. Last time I checked, you have to go through some hoops, but it's not that difficult to set up.
See for example this question
For best security, you need one dedicated database account per user; each account should only have the privilegeds necessary for the tasks that the corresponding user may perform. Normally you grant privileges to roles (e.g. "clerk", "manager", "supervisor") and grant those roles to the users. Obviously, it requires some work to identify which privileges each role needs. In many cases, it might be necessary to not allow direct access to some tables, but only to database views that hide some parts that should not be visible to that role, or to stored procedures that do some additional checks and make sure that each transaction is processed as a whole.
We are about to migrate an intranet web application from using a proprietary forms-based security to Active Directory. The application logs a variety of user actions, and there is a significant amount of data associated with user accounts. Our plan was to migrate all of these UserId columns in various tables: from a foreign key linking the proprietary system, to an Active Directory GUID. Login names are identical between the two systems, so migrating is not an issue.
However, we identified one major problem: Our security policy dictates that inactive users must be deleted from Active Directory. An orphaned GUID in our security logs makes the entries pretty meaningless to anyone viewing them.
How can an application maintain the human-readable basics (name, login, etc.) about a GUID that has been deleted from Active Directory?
We have considered the following options. One of these options may end up being the optimal, but we wish to try for better:
Denormalize the log tables and store name/login instead of a GUID (okay for logs, not so much for active data.)
Maintain a "cache" of AD object information where entries are never deleted
Keeping the AD account but deactivating/locking it down
I wouldn't fully denormalize the log table, but instead store the pertinent AD information alongside the GUID, as Tim said. However, if you will need this AD information in other areas, cache it in your user table. I would recommend against changing your security policy.
For logging, I favor the denormalized approach, but maintaining the id. I store the user's id along with other, human-readable indentifying information. For active user's I can still use the id in joins (if necessary). For inactive (deleted) users I have the human-readable form for use by the auditors.
We have decided to use a "cache" table that will store a dictionary of GUIDs that map to friendly user information. This will require a view that abstracts an AD user list, and coalesces in missing entries from the cache.