Prevent SQL Injection when the table name and where clause are variables - asp.net

I have a situation need your help.
At the moment, i've build an asp.net app using ado.net. I'm using CommandText to build dynamic query so it have SQL Injection vulnerability.
My CommandText like this
String.Format("SELECT COUNT(*) FROM {0} {1}", tableName, whereClause)
TableName and whereClause is passed in by developer. As you see I cannot use SQLParameters here because I need to pass entire tableName and whereClause not only parameter values.
My solution to prevent SQL Injection is using BlackList check TableName and whereClause to find out malicious string but I don't know this is the best way in this situation, isn't it. And if it is anyone can help me where to find BlackList references or library.

Without knowing further details, there are several options you have in order to avoid SQL injections attacks or at least to minimize the damage that can be done:
Whitelisting is more secure than blacklisting: Think about whether you really need access to all the tables except the blacklisted ones. If anyone adds tables at a later point in time, he or she might forget to add them to the backlist.
Maybe you can restrict the access to a specific subset of tables. Ideally, these tables follow a common naming scheme so the table name can be validated against that scheme. If there is no naming scheme, you could also add a list of the tables that can be accessed in the program or the application configuration so you can check whether the table name is contained in this list. If you save the list in a configuration file, you are able to expand the list without compiling the application again.
If you cannot whitelist the table names, you could at least check whether the supplied table name is present in the database by querying the sys.tables system table (in SQL Server, other DBMS might have similar tables). In this query, you can use parameters so you are safe.
For SQL Server, you should put the table name in square brackets (SELECT COUNT(*) FROM [" + tableName + "]"). Square brackets are used to delimit identifiers (also see this link). In order for this to work, you have to check that the tableName variable does not contain a closing square bracket. If the tableName variable might contain a schema identifier (e.g. dbo.MyTable you'd have to split the parts first and then add the square brackets ([dbo].[MyTable]) as these are separate identifiers (one for the schema, one for the table name).
Validate the contents of the variables very carefully by using regular expressions or similar checks. This is easy for the table name, but very hard for the WHERE clause as you'd basically have to parse the SQL WHERE clause and assert that no dangerous code is contained.
The hardest part is to check the WHERE clause. Also in this respect it would be best, if you could limit the options for the user and whitelist the possible WHERE clauses. This means that the user can choose from a range of WHERE clauses that the program knows or builds based upon the user input. These known WHERE clauses could contain parameters and therefore are safe against SQL injection attacks. If you cannot whitelist the WHERE clauses, you'd have to parse the WHERE clause in order to be able to decide whether a certain request is dangerous or not. This would require a large effort (if you don't find a library that can do this for you), so I'd try to whitelist as many parts of the dynamic query as possible.
In order to reduce the damage of a successful attack, you should run the query under a specific account that has very limited rights. You'd have to add another connection string to the config-file that uses this account and create the connection with the limited connection string. In SQL Server, you could move the tables that this account is able to access to a specific schema and limit the access to this schema for this account.
Protect your service very well against unauthorized access so that only trusted developers can access it. You can do this by using some components in the infrastructure (firewalls, transport-level security etc.) and also by adding a strong user authentication mechanism.
Log each request to the service so that the user and machine can be identified. Notify the users about this logging mechanism so that they know that they will be identified should anything go wrong.
Some final thoughts: even if it seems very easy to provide developers with such an open method for querying data, think about whether it is really necessary. One possible option would be to not have this open access, but instead configure the queries other developers need in a configuration file. Each query gets an identifier and the query text is stored in the file and therefore known beforehand. Still, you are able to add new queries or change existing ones after you have deployed the service. You can allow parameters in the query that the callers specify (maybe a numbered parameter scheme like p1, p2, ...).
As you can see from the list above, it is very hard (and in some areas close to impossible) to lock the service down and avoid all kinds of SQL injection attacks once you allow this open access. With an approach as described in the last paragraph you loose some flexibility, but you wouldn't have to worry about SQL injection attacks anymore.

Related

Is there a way to enforce a schema constraint on an AWS DynamoDB table?

I'm a MSSQL developer who recently was tasked with building a new application using DynamoDB since we use AWS and we wanted a highly scaleable database service.
My biggest concern is data integrity. For example, I have a table for all my users where every row needs to have a username, email, and name field, all strings, with a verified field that's an int. Is there anyway to require all entries in that table to have those fields and to be of that particular type?
Since the application is in PHP I'm using Kettle as my ORM which should prevent me from messing up the data integrity but another developer voiced a concern about if we ever add another application or if someone manually changes some types via the console.
https://github.com/inouet/kettle
Currently, no, you are responsible for maintaining the integrity of your items with respect to the existence of attributes that are not keys on the base table. However, you can use LSI and GSI to enforce data types of attributes (notwithstanding my qualm that this is not a recommended pattern, as it could cause partition heat especially for attributes whose range of values is small). For example, verified seems like it might take only 0 or 1 as a value, so if you create a GSI with PK=verified where verified is a Number, writes to the base table may get throttled by the verified GSI.

sql server generate all select script (asp.net)

I'm in the process of developing an application that allows users to select tables and columns, and choose join methods ( like inner, outer..) as well as aggregate functions sql (sum, avg..etc) for the purpose of generating reports from those selections.
What I did is append strings to build a request to an sql server. I think i'm wrong doing it this way because users can choose a lot of columns and that throws unexpected exceptions. Are there some ideas on a better way to go about this (not source code)?
As you have asked, what is best way to manage query ( can contain sum,avg etc..) generated on server side and made those to execute on SQL server, I am writing best possible suggestion for this. Consider that and follow your path.
If you have adhoc queries generated in server side, then definitely you can write those into SQL group of statements known as Stored Procedure . And this has following advantages.
More manageable, if same set of SQL blocks need in multiple places, then use this single procedure everywhere.
Secure - you don't have to set permission( like select) for multiple tables (joining tables), instead just have execute permission for procedure.
Good Performance - Execution Plan Caching and Reuse
Source - http://weblogs.asp.net/fbouma/38178
Stored proc - http://msdn.microsoft.com/en-us/library/ms190782.aspx
If you are new to stored procedure and want to know, how to use that in asp.net, here is tutorial for this - http://www.dbtutorials.com/advanced/using-stored-procedures-cs/

Which is better NEWID or Encrypted ID?

I have an application that allows users to register for events. The database (SQL Server) has names, email addresses, addresses and phone numbers.
I pass id information via the query string (for example event.aspx?id=____). Presently I am using the "unique" identifier provided by NEWID() and the performance is great.
I was debating whether or not this is a reasonably secure approach. Should I encrypt the id values and pass that in the query string instead? For example instead of generating the unique id by using NEWID I would take the integer value that is in the primary key column and encrypt and decrypt that as needed in the application.
I have done this and noticed a performance hit. Any thoughts?
passing an anonymous key is perfectly fine. What's more of a risk is SQL injection attacks, but if you are taking precautions (e.g. using stored procedures, parameterized SQL etc...) you should be fine.
If someone can change the value of id and still register (thus altering/viewing someone else's registration information), then yes, you have a problem.
If you are ensuring that a person can only modify their own registration, then you likely do not have an issue. In this case, you could use the SQL ID column anyway instead of generating a NEWID() (unencrypted -- what is the threat if they know the ID?). If only the correct person can modify/register then revealing the ID shouldn't be a concern. Though I'm curious though as to why a simple encrypt/decrypt is negatively impacting performance.

semaphore for a datarow

I am writing a web application that allows the user basic CRUD operations against a database. The tables that are being updated have less than 200 records and there may be multiple users using this applications there is a need for some sort of locking mechanism to avoid the 2 users from overwriting each others changes.
I have looked into semaphores but that seems to only limit the number of users executing the same code. In my data layer I have a class file for each table so I can certainly employ this on a specific table's class file but can I somehow limit the locking to the key fields?
Assuming that you are using a proper SQL implementation along with ASP .Net, why dont you use transactions to achieve this? Check it out here.
Additionally, you can also read up on optimistic concurrency to see if that is what you need. Basically, before saving a value, the user checks if the value in a particular field is the same as it was when he first read it. If the value is the same, it is assumed that noone else has overwritten it, and the new value is saved to the DB; if the values are not the same, a warning message is returned instead.

Building an import process that checks for duplicates

Using ASP.NET, I'm building an admin tool that requires a function to import a list of email addresses. Upon uploading the file, I want to check for existing records for any of the email addresses supplied. For non-existing email addresses, I would create them using my DAO.
Basically I want to:
Receive list of emails
Retrieve data for existing emails
Create data for new emails in db
Return full data for all emails in list.
Since I want to know which of the emails exist up front, my first thought was to query the table for all records WHERE Email IN ('Email001FromFile', 'Email002FromFile', 'etc...') but the list could potentially contain thousands of email addresses, and I'm not certain supplying that many email addresses to the IN operator would be a good idea.
I also thought about looping through the list and checking for a record for each email, but that would potentially generate far too many queries.
My next thought was to generate a temp table to hold the list and modify the IN clause to use the temp table, rather than an explicit list of items, but that would require I execute SQL or a stored procedure directly, which I'm not inclined to do since I'm using NHibernate to access my DB.
Though I am using ASP.NET (C#) and NHibernate, and any answers specific to that would be helpful, I'm really just looking for general ideas on how to handle this scenario.
If loading the existing e-mails into memory is not an option I would maybe go for some kind of batch approach. Go for the IN-query you mention, but do it only for n emails at time. You could eiter hardcode n to a certain value or you could let it be a function of the total number of new e-mails.
I'm not sure whether this approach really is faster than to perform one single IN-query (someone with more db-skills than me would have to answer that), but that would allow you to indicate some kind of loading status to the user.
Are you doing anything with the emails that are duplicates?
You could put a UNIQUE constraint on your table to only allow an email address to be entered once - then catch the exception SQL will throw when you attempt to insert a duplicate.

Resources