I'm currently writing a web app which would largely be used by developers, and I figured (from personal experience) that there would be times where it would be handy to run custom searches in an unrestricted way. I would like to let my users run arbitrary multi-statement SQL searches on their personal data (for an extra fee), so they can retrieve the data that's relevant to their question at the time.
Obviously, this is something that needs to be done with extreme caution, so I would like to make sure I'm going to tackle this the right way.
As I see it, the main points of concern are:
A malicious user could run a DOS (can track this via logging and remove their permissions)
Someone could run a function in a malicious way
Someone could access/modify data that doesn't belong to them (including database schema)
Someone could delete or modify data in a query (I would prefer they do that in a controlled manner)
What would be the safest way to go about providing this kind of ability to users safely?
This is dangerous territory (and I strongly recommend you weigh up this requirement carefully due to the obvious dangers you will be exposing yourself to), however I will try to give you the safest way to proceed if you must.
The only assumption I am making here is that you are running a current version of PostgreSQL and that you require users to remotely connect to the server (using their own tools) to execute their custom queries. Even if they will be entering them into a webpage, most of the same techniques will still apply as long as they each have a separate user log in for the database server.
First, (as NoBugs pointed out) to prevent users executing obvious malicious statements (like UPDATES, DELETES, DROPS, etc) you need to ensure that the user account connecting to the server has only SELECT permissions on the db(s) and table(s) they should be able to read from. Have a look in manual to see how to define roles for users, and grant specific permissions to those roles.
http://www.postgresql.org/docs/9.0/static/user-manag.html
http://www.postgresql.org/docs/9.0/static/database-roles.html
Note that you can only limit a user down to a particular table. If
users each need to be given access to different parts of a table, then
PostgreSQL (and nearly all DBMS's) will not support this out of the
box. Your only option would be to try and create some kind of SQL/TCP
proxy that intercepts requests, and modifies them somehow to limit
query results, before passing on to the database server. This would be
extremely difficult even for a very experienced developer!
To prevent (or at least detect) DOS attacks, you will need an external script or process to keep an eye on the resource usage of the database (and/or the entire server) every few seconds, and possibly build in a mechanism to restart the PostgreSQL service if it is maxed-out.
You will need to experiment with how long before you should intervene
carefully, as it is quite possible for a legitimate query to max
things for a few seconds.
As you mentioned, you would need to keep a careful log of who was trying to execute what, & when so, if necessary you can work backwards from a failure, to find out the culprit. You can really only rely on the system logs for this, which can be configured to write out to files, CSV, or Syslog.
I would suggest you pre-create some tools to help you quickly search
these logs to find what you need before you need to try and find it
(pun intended).
Finally you should also try to follow the other standard best practices for administration and security (all of which can be found in the manuals) including:
Only allow access for your users from specific ip's/hosts (dont give the general public any chance at connecting to your server. Your customers will need static IP's to access the system, but this is certainly worth considering to mitigate risks.
Keep a close eye on all of your standard administrative tasks for the server (especially backups, disk space, log file maintenance, index usage, etc.)
Make sure the user the sql is running as has permissions only to the tables/files the user should be able to modify.
There are also some other considerations - only allow trusted input (maybe use https in your api calls?) and know Mysql could access files and stuff you wouldn't want to let it access.
See also: http://www.greensql.com/article/protect-yourself-sqli-attacks-create-backdoor-web-server-using-mysql
Related
I built a software for a farm using C#, the program was meant to keep track of the inventory and the financial exchanges related to the farms work.
The software was built to be installed on the manager's computer who then entered the farms data and retrieved reports and so. While the accountant used the same PC to use the financial part of the program with a different account.
Now the farm's business grew and more users need to use the system, can I move the database with the old data to a server so users can log in the system from different PC's at the time and continue the old tasks?
If I can - what do I change in my code?
P.S. the database was done in MS Access.
Not a lot of information to go on here. I can tell you that Access is a file based database system, and so whilst you could put the database files on a server or a NAS device with no problem with multiple users you should expect to run into the usual problems of Windows file sharing - VERY SLOW performance as a minimum.
It is also possible that the database may have been limited to a single user at a time, and without any more information impossible to know whether the developers have allowed for multi-user at all or whether you could have a situation where if several people do open the file at once one person may be overwriting another's data leading to corruption.
The short answer is that if the original developers are no longer around and you cannot ask the question of them then you probably need a new dedicated application to do the work which would mean either a complete rewrite or an alternative commercial application.
For multi-user Microsoft SQL Server, MySql, or even Firebird or another dedicated database back end would be the way to go. The front end could be anything - Winforms, WPF, even a web application if that is what you want, but it would have to be written.
I hope that this is helpful.
What native technology exists to encrypt/decrypt a string in the database for reading into a single application?
Scenario:
I have a set of connection strings that I need to use to securely access a set of production servers, for a polling application. I would like to store those in a table in a database and pull them out as I need them via a service. That will give me the ability for a handful of users (with permissions) to edit/add those entries.
My target audience using this application are all developers, these are servers to monitor our production and staging environments for some specific SQL flaws that I may need to later fix. This is a devops application.
Knowing that my target audience is developers, and that these are production servers, I would like to "lock the door" to keep people from actively seeing the production passwords/useraccounts unless they need them (auditing purposes). I realize that a lock is only as good as the frame around the door, and is only to keep honest people and petty thieves out, and that anyone dedicated will eventually be able to get past whatever safeguards I try to set.
Problem:
What technology in C# exists to secure this information and still allow me to dynamically add/alter connection strings but still keeps the data in the database reasonably secure? I am willing to make some changes to a machine.config or the like, but I need to actively develop the application too, so would like if it could be done in either machine.config1 or web.config, to allow for local development before deployment to the devops servers.
I understand that some of my alternative suggestions are:
Use strong database passwords to keep people out
Use strong schema organization to keep people out
Trust the developers, they work for your org (see "audit trail". I need to make some stab at securing production credentials)
Don't let people have access to the server and store them in the web.config (already plan on this in the first place)
Ideally:
Ideally I would just use a private key for encryption/decryption on the application server, but I don't exactly know the most secure way to do this, other than base64. I know this is not encryption.
What technology exists in the .NET native stack to securely encrypt/decrypt a string that may contain special characters in a single application and what is an example usage of this technology?
If I knew a name and technique, I would not be asking this question.
1 using machine.config/web.config to indicate something inherent in the .NET stack. I'm open to any suggestions.
Saving connection information in a database table is going to be unsecure, always. At some point, you're going to have to decrypt the password, and send it to the server. Developers tend to be smart enough to figure out any "security by obscurity" approach, and get to the passwords at some point. Even if you encrypt the password in the DB (not too hard), as long as you pass it to the SqlConnection at some point, you still have to decrypt it somewhere on the user (developer) end.
Rather, the only way to do this securely, is to make sure the password actually never gets anywhere close to the developers (or anyone else). There's a few ways to handle this:
Use an external security provider, such as Windows authentication. This means you don't have to use any username or password at all.
Create some kind of a tunnel to send any required SQL. This is very easy if your developers only ever need to run SQL commands, and a bit trickier if they want to use productivity tools like Management Studio; however, even that's doable - SQL can run fine over TCP, and you should be able to emulate that quite easily. Only the tunneling server would have access to the actual credentials, your developers would only have credentials to the tunneling server (and limited ones at that).
Use the Linked servers feature. This allows you to link local users (your devs) to remote users (su on the target server or whatever). It should work just fine with all the usual security settings.
Out of these, I'd say linked servers might be the best. They're quite easy to use, they can be administrated by the select few, and they don't publish the password at all. You can also do queries that span servers this way - very handy for a maintenance tool :)
Windows authentication is incredibly useful, but usually only on LAN, since we're talking about having all the DB servers in a domain. VPN could help, but that's getting into complicated territory.
Using a tunnel isn't necessarily a bad idea, although I assume you'll run into a few issues before you get it working 100%. And in the end, that's what Linked servers do for you for free, so why not use that?
Now, if you really do want to go through with the encryption idea instead, you can pick from a plenty of .NET supported encryption schemes. AES should work fine - it's assymetrical, so knowing the encryption key doesn't mean you can decrypt the data (the decryption / private key should only be stored in a secure location and on the maintenance application server, in a place noone but the application itself can reach; do note that admins can reach anything, so if your people have administrator rights, this isn't going to work).
For an example, see the AesManaged class in System.Security.Cryptography - http://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged(v=vs.110).aspx
Most applications only need one database, but you can use the Manager to create as many as you need. Multiple databases are independent of each other. If your application supports switching between multiple users, each with their own separate content and settings, you should consider using a database for each user. Otherwise, it's usually best to stick with one database.
I'm tasked with designing a .Net application that will download a sql script file from a specific server and execute that file against a database. I can think of a number of security steps I'll want to include:
Use a secure connection to the server (SFTP)
Database user only has certain access (insert, update data on specific tables)
I suggested sandboxing the transaction in a separate database instance.
Unfortunately, they say the transfer data set is too large for this
to be practical.
I'm primarily worried not only about allowing someone to purposefully damage information in a very large database, but, ideally, to help prevent accidental damage as well.
Questions:
Did I miss anything? Are there any best practices to keep in mind
for this kind of thing?
What would be the best way to authenticate the server cert against a man-in-the-middle attack?
To point 1)
Keep an audit log.
To whatever degree possible, help the user create these SQL scripts. Drop downs to choose table names, radio buttons to choose the command, a column selector, etc... This will help prevent accidents.
Ideally, you would be able to roll back to before any specific script is executed (think of how a bank has to be able to replay your transactions to verify your account balance if ever questioned). Depending on the frequency of updates and this data's importance, you're probably fine with just some daily backups instead of an actual transcriptional, re-playable history.
To point 2)
WinVerifyTrust to make sure the certificate is valid and has a valid root.
CryptQueryObject to check for a specific certificate.
I would implement your point 2 as restrictive as possible, but obviously your script has to be allowed to do some stuff. So you will have to trust the person which provides the script. To make sure that you execute a script which is really from that person you trust, I would sign the script and would validate the signature before executing the script. So you can be sure that it has not been modified by somebody else.
I am designing a program that will build and maintain a database, and act as a central server. This is the 'first stage' of a grander plan. Coming later will be 3-5 remote programs built around the information put into this database.
The requirements are:
The remote programs must be able to access the information in the database.
The remote programs must be able to set alerts when information in the database changes.
The remote programs must be able to request the central server to go out and fetch new / different data.
So, the question is this: how do I expose this data and events to the outside world? My two choices are:
Have them communicate directly with my 'server' application. This seems easier to:
do event notifications (although I suppose I'm probably missing something in SQL).
It also seems like this is more 'upgradeable' - that is I don't need to worry about the database updating and crashing all my remote programs because something changed. I can account for this and transform it the data to a version the child program will understand.
Just go ahead and let them connect directly to the database.
This nice thing about this is that it's solved. I can use LINQ for SQL. The only thing the main server application needs to do is let the remote programs know where the database is.
I'm unsure how to trigger / relay 'events' for field changes in a database over different programs that may or may not be on the same computer.
Forgive my ignorance on this question. I feel woefully unprepared to ask it, but I'm having a hard time figuring out where to get started with this. It is my first real DB project :-/
Thanks!
If the other programs are going to need to know about updates to the database, then the best solution is to manage all db updates through your server application so it can alert clients of the changes. Otherwise it will be tough for the clients to be aware of changes to the db. This also has the advantage of hiding the implementation details of your storage solution from the clients, so you are free to change databases, etc...
My suggestion would be to go with option 1. Build out a web service that can provide the information they all need. This will be the most flexible and allow you to reduce duplicate backend code that would happen with direct communication with the database.
I would recommend looking at some Data Source design patterns first. This types of patterns will help you come up with solutions about how to manage the states of your data. Otherwise I think that I would require some more information about your requirements for the clients to make any further useful suggestions.
I recommend you learn about SQL Server and/or databases first. You don't appear to realize that most of what you want from your "central server" can all be done by SQL Server itself.
A central databse is the simplest option and the cheapest to both build and maintain.
There are however a few scenarios where a central database could cause problems:
High load on one of the systems: A high load on one of the systems could reduce performance on the other systems. For example someone running an internal report stops you being able to take orders on your eCommerce site.
With several systems writing to the same database there is a greater chance of locking.
With several systems dependent on the same database schema, how do you upgrade? All systems at the same time?
If you need to take down the database all systems stop.
I am working on an application that will allow users to create queries on their own to view data in their database. However the stipulation is that the application should prevent any modification of the tables and data stored in the database. The Application will be written in C#. Any good suggestions of how this could be done? Possible idea that I have thought of:
Parse SQL to filter for any reserve word that may alter data(i.e. insert, alter, ect)
There maybe a setting that may prevent modification from this applications connection.
Any suggestion to block any changes made from this application to prevent any chance of a user error or attempt to modify tables of data is much appreciated.
You should run your queries as a user that doesn't have write permission.
Any decent DBMS should have these protections already built in (at a per-user level). You just make sure the only access they have is read-only.
Then you don't have to worry about anything that they do. Let them try to insert, update and delete all they want.
It's a basic tenet of databases that they are responsible for their own security and integrity. You never leave that up to an external application since any monkey can write an application to connect to the database that doesn't follow the rules.
This needs to be handled at the user level rather than the query level. When you set up your app, you'll need to make sure that the account used to run the queries does not have any dbwriter permissions.
This is usually handled by giving users access to (non-updatable) views, but not to tables.
IMHO, the best way is to create a user that can only do select on specified tables. And then use that user for connection.