I need to verify that a run-time user-supplied SQL query is only used to SELECT data - and can in no way execute other operations (delete, update, insert, ..) or alter the database (alter, create, drop, truncate, ...)
I am not looking for a restricted-user solution (may be implemented later), but for a C# query "white-listing".
Currently, this is the code I am using :
private bool ValidateDatasourceQuery(String datasourceQuery)
{
bool result = false;
try
{
bool isValid = true;
String query = datasourceQuery.Trim().ToLower();
if (query.Substring(0, 6) != "select") { isValid = false; }
if (query.Contains("delete ") || query.Contains(" delete")) { isValid = false; }
if (query.Contains("exec ") || query.Contains(" exec")) { isValid = false; }
if (query.Contains("insert ") || query.Contains(" insert")) { isValid = false; }
if (query.Contains("update ") || query.Contains(" update")) { isValid = false; }
if (query.Contains("alter ") || query.Contains(" alter")) { isValid = false; }
if (query.Contains("create ") || query.Contains(" create")) { isValid = false; }
if (query.Contains("drop ") || query.Contains(" drop")) { isValid = false; }
if (query.Contains("truncate table ") || query.Contains(" truncate table")) { isValid = false; }
result = isValid;
}
catch (Exception exception) { GUC_Utilities.TraceError(exception); }
return result;
}
Any thoughts and ideas? Are there ways to pass through this check and execute a dangerous operation like DELETE? How would you improve this code?
Also another question, is ExecuteReader method only able to run SELECT statements, or could also run other CRUD operations? Like in the following code :
//execute command
SqlCommand sqlCommand = new SqlCommand(sql, sqlConnection);
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
dataTable.Load(sqlDataReader);
Thanks for your time!
PS I am only interested in improving & validating the given code - no GUI, specific roles & other suggestions are currently an option
EDIT (2014-01-16) : After further research and tests, I can confirm that there IS NO RELIABLE WAY to prevent hackers injecting destructive statements inside your SQL query (semicolons, character injections, built-in functions, etc.). The only way to maintain data integrity is TO CREATE A SPECIFIC USER ROLE WITH LIMITED SET OF PRIVILEGES. Everything other must be considered as potentially unsafe. As well, note that EXECUTEREADER can indeed run DELETE, UPDATE and INSERT statements.
SELECT * FROM whatever WHERE somevarchar="drop"SELECTonly) - what happens if a new dangerous command is added? Which is going to highlight the first large problem: you won't always findSELECTin the first six characters - you're eliminating CTEs, which can be a huge help in certain types of queries. It might help to know what the anticipated dataset is - if you work for a clothing company"Alter"is likely a common string... Heck, I'm assuming there's an"Executive"job title at your company... and Unicode might still bite you.SEL/*comment*/ECTwould work.