SQL injection single quote Vulnerability - c#

Hello I'm security testing a website I'm working on. Some developer tried to avoid SQL injection by replacing every single quote with double quotes. This is the C# code:
string sql =
#"SELECT *
FROM users
WHERE us_username = '$us'
AND us_password = '$pw'";
sql.Replace("$pw", txtPassword.Text.Replace("'","''"));
Is there any way that I can perform a SQL injection attack? I've tried the Unicode trick but it didn't work. The database runs on SQL Server 2008R2.

You should use parameterized command instead. Using string.Replace is just a bad idea.
var command = conn.CreateCommand();
command.CommandText = #"SELECT *
FROM users
WHERE us_username = #user
AND us_password = #password";
cmd.Parameters.Add("#user", txtUser.Text);
cmd.Parameters.Add("#password", txtPassword.Text);
This might be a potential candidate for your setup :
As an example, note the following trivial Stored Procedure:
create procedure GetData ( #param varchar(20) ) as
begin
declare #s varchar(200)
select #s = 'select * from dataTable where name = ''' + #param + ''''
exec (#s)
end
This SP may be called from a Web page, which executes validation code
before passing the input to the SP. At a minimum, this validation code
either verifies that the input does not contain a quote, or sanitizes
it to double any existing quote. For instance, the validation code may
be using string.Contains(), string.Replace(), Regular expressions,
etc. It is also possible that this Web page is behind a finely-tuned
Web Application Firewall that validates all input and verifies that no
quotes are included. A malicious user or attacker can submit malicious
code containing a modifier letter apostrophe (U+02BC, URL encoded to
%CA%BC). This will easily pass applicative validation code and WAF
filters, since these search for an actual quote (U+0027) which does
not exist in the input at this time. Obviously, IDS/IPS systems would
also not detect anything amiss. The validation mechanisms may even
search for various encodings of a quote, such as URL Encoding, UTF-8
encoding, Hex encoding, double encoding, and more – however, U+02BC is
none of these, and is in fact a completely different character value.
And this is where the interesting (or scary) part starts – the Unicode
homoglyph translation is not limited to base alphabet characters...
Specifically, the Unicode character U+02BC (modifier letter
apostrophe) can be translated by the database server to a simple quote
– ' (U+0027). There are, of course, many other similar examples.
Source : http://web.archive.org/web/20130401091931/http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf

The code for that partical query is safe from SQL injection, but only when used with a certain databases. Each system has its own set of characters that needs escaping, so if you use that with for example MySQL then it's not safe. Other queries might not be safe.
The code should be replaced nevertheless as it is broken. As you need to fix the code you should also change it to using parameterised queries, which is a more robust and portable solution.
So, let's see what's broken. As the code is replacing one parameter at a time, they may interfer with each other. If I for example enter the user name has$$$pwnd and the password 1234 (yeah, weak password), you end up with a query that looks like:
SELECT *
FROM users
WHERE us_username = 'has$$1234nd'
AND us_password = '1234'
If some values contain the codes that is used for parameters replaced after it, the values become broken.
This could even be used to make an SQL injection in other queries in the code, if there are parameters of different types and the values are not properly verified. As values from one parameter can end up in another parameter, a string value could end up in a numeric parameter which doesn't have apostrophes around it, thus there is no need to sneak in an apostrophe to break out of a string literal to put harmful code in the query.

The best way to counter SQL Injection is to add parameters.
SqlCommand sql = new SqlCommand (#"SELECT *
FROM users
WHERE us_username = #user
AND us_password = #password")
sql.Parameters.Add("#users", SqlDbType.Varchar2, 5).Value = "users";
sql.Parameters.Add("#user", SqlDbType.Varchar2, 6).Value = "your_value";
sql.Parameters.Add("#password", SqlDbType.Varchar2, 8).Value = "your_value";
As you can see, you can do quite a bit to ensure what is being executed are the values that you want to only get executed.
What the developer has coded will only alter the sql statement after the fact, which is good if they are logging this sql statement. What you have now however will not protect against Sql Injection.

Related

c# asp.net compare dates in where clause in sql query [duplicate]

This question already has answers here:
How can I add user-supplied input to an SQL statement?
(2 answers)
Closed 7 years ago.
I have to program an application management system for my OJT company. The front end will be done in C# and the back end in SQL.
Now I have never done a project of this scope before; in school we had only basic lessons about SQL. Somehow our teacher completely failed to discuss SQL injections, something which I have only now come in contact with by reading about it on the net.
So anyway my question is: how do you prevent SQL injections in C#? I vaguely think that it can be done by properly masking the text fields of the application so that it only accepts input in a specified format. For example: an e-mail textbox should be of the format "example#examplecompany.tld". Would this approach be sufficient? Or does .NET have pre-defined methods that handle stuff like this? Can I apply a filter to a textbox so it only accepts email-address format or a name textbox so it doesn't accept special chars?
By using the SqlCommand and its child collection of parameters all the pain of checking for sql injection is taken away from you and will be handled by these classes.
Here is an example, taken from one of the articles above:
private static void UpdateDemographics(Int32 customerID,
string demoXml, string connectionString)
{
// Update the demographics for a store, which is stored
// in an xml column.
string commandText = "UPDATE Sales.Store SET Demographics = #demographics "
+ "WHERE CustomerID = #ID;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml);
try
{
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
My answer is quite easy:
Use Entity Framework for communication between C# and your SQL database. That will make parameterized SQL strings that isn't vulnerable to SQL injection.
As a bonus, it's very easy to work with as well.
SQL injection can be a tricky problem but there are ways around it. Your risk is reduced your risk simply by using an ORM like Linq2Entities, Linq2SQL, NHibrenate. However you can have SQL injection problems even with them.
The main thing with SQL injection is user controlled input (as is with XSS). In the most simple example if you have a login form (I hope you never have one that just does this) that takes a username and password.
SELECT * FROM Users WHERE Username = '" + username + "' AND password = '" + password + "'"
If a user were to input the following for the username Admin' -- the SQL Statement would look like this when executing against the database.
SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''
In this simple case using a paramaterized query (which is what an ORM does) would remove your risk. You also have a the issue of a lesser known SQL injection attack vector and that's with stored procedures. In this case even if you use a paramaterized query or an ORM you would still have a SQL injection problem. Stored procedures can contain execute commands, and those commands themselves may be suceptable to SQL injection attacks.
CREATE PROCEDURE SP_GetLogin #username varchar(100), #password varchar(100) AS
DECLARE #sql nvarchar(4000)
SELECT #sql = ' SELECT * FROM users' +
' FROM Product Where username = ''' + #username + ''' AND password = '''+#password+''''
EXECUTE sp_executesql #sql
So this example would have the same SQL injection problem as the previous one even if you use paramaterized queries or an ORM. And although the example seems silly you'd be surprised as to how often something like this is written.
My recommendations would be to use an ORM to immediately reduce your chances of having a SQL injection problem, and then learn to spot code and stored procedures which can have the problem and work to fix them. I don't recommend using ADO.NET (SqlClient, SqlCommand etc...) directly unless you have to, not because it's somehow not safe to use it with parameters but because it's that much easier to get lazy and just start writing a SQL query using strings and just ignoring the parameters. ORMS do a great job of forcing you to use parameters because it's just what they do.
Next Visit the OWASP site on SQL injection https://www.owasp.org/index.php/SQL_Injection and use the SQL injection cheat sheet to make sure you can spot and take out any issues that will arise in your code. https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet finally I would say put in place a good code review between you and other developers at your company where you can review each others code for things like SQL injection and XSS. A lot of times programmers miss this stuff because they're trying to rush out some feature and don't spend too much time on reviewing their code.
SQL injection should not be prevented by trying to validate your input; instead, that input should be properly escaped before being passed to the database.
How to escape input totally depends on what technology you are using to interface with the database. In most cases and unless you are writing bare SQL (which you should avoid as hard as you can) it will be taken care of automatically by the framework so you get bulletproof protection for free.
You should explore this question further after you have decided exactly what your interfacing technology will be.

Inserting into an oracle DB is not working with string literal, was wondering if there was a bind command I could use [duplicate]

This question already has answers here:
How can I add user-supplied input to an SQL statement?
(2 answers)
Closed 7 years ago.
I have to program an application management system for my OJT company. The front end will be done in C# and the back end in SQL.
Now I have never done a project of this scope before; in school we had only basic lessons about SQL. Somehow our teacher completely failed to discuss SQL injections, something which I have only now come in contact with by reading about it on the net.
So anyway my question is: how do you prevent SQL injections in C#? I vaguely think that it can be done by properly masking the text fields of the application so that it only accepts input in a specified format. For example: an e-mail textbox should be of the format "example#examplecompany.tld". Would this approach be sufficient? Or does .NET have pre-defined methods that handle stuff like this? Can I apply a filter to a textbox so it only accepts email-address format or a name textbox so it doesn't accept special chars?
By using the SqlCommand and its child collection of parameters all the pain of checking for sql injection is taken away from you and will be handled by these classes.
Here is an example, taken from one of the articles above:
private static void UpdateDemographics(Int32 customerID,
string demoXml, string connectionString)
{
// Update the demographics for a store, which is stored
// in an xml column.
string commandText = "UPDATE Sales.Store SET Demographics = #demographics "
+ "WHERE CustomerID = #ID;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml);
try
{
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
My answer is quite easy:
Use Entity Framework for communication between C# and your SQL database. That will make parameterized SQL strings that isn't vulnerable to SQL injection.
As a bonus, it's very easy to work with as well.
SQL injection can be a tricky problem but there are ways around it. Your risk is reduced your risk simply by using an ORM like Linq2Entities, Linq2SQL, NHibrenate. However you can have SQL injection problems even with them.
The main thing with SQL injection is user controlled input (as is with XSS). In the most simple example if you have a login form (I hope you never have one that just does this) that takes a username and password.
SELECT * FROM Users WHERE Username = '" + username + "' AND password = '" + password + "'"
If a user were to input the following for the username Admin' -- the SQL Statement would look like this when executing against the database.
SELECT * FROM Users WHERE Username = 'Admin' --' AND password = ''
In this simple case using a paramaterized query (which is what an ORM does) would remove your risk. You also have a the issue of a lesser known SQL injection attack vector and that's with stored procedures. In this case even if you use a paramaterized query or an ORM you would still have a SQL injection problem. Stored procedures can contain execute commands, and those commands themselves may be suceptable to SQL injection attacks.
CREATE PROCEDURE SP_GetLogin #username varchar(100), #password varchar(100) AS
DECLARE #sql nvarchar(4000)
SELECT #sql = ' SELECT * FROM users' +
' FROM Product Where username = ''' + #username + ''' AND password = '''+#password+''''
EXECUTE sp_executesql #sql
So this example would have the same SQL injection problem as the previous one even if you use paramaterized queries or an ORM. And although the example seems silly you'd be surprised as to how often something like this is written.
My recommendations would be to use an ORM to immediately reduce your chances of having a SQL injection problem, and then learn to spot code and stored procedures which can have the problem and work to fix them. I don't recommend using ADO.NET (SqlClient, SqlCommand etc...) directly unless you have to, not because it's somehow not safe to use it with parameters but because it's that much easier to get lazy and just start writing a SQL query using strings and just ignoring the parameters. ORMS do a great job of forcing you to use parameters because it's just what they do.
Next Visit the OWASP site on SQL injection https://www.owasp.org/index.php/SQL_Injection and use the SQL injection cheat sheet to make sure you can spot and take out any issues that will arise in your code. https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet finally I would say put in place a good code review between you and other developers at your company where you can review each others code for things like SQL injection and XSS. A lot of times programmers miss this stuff because they're trying to rush out some feature and don't spend too much time on reviewing their code.
SQL injection should not be prevented by trying to validate your input; instead, that input should be properly escaped before being passed to the database.
How to escape input totally depends on what technology you are using to interface with the database. In most cases and unless you are writing bare SQL (which you should avoid as hard as you can) it will be taken care of automatically by the framework so you get bulletproof protection for free.
You should explore this question further after you have decided exactly what your interfacing technology will be.

table name sql injection

I am working with C#. I need to write a select inline query.
The table name should be taken from config. I cannot write a stored procedure.
SqlCommand myCommand= new SqlCommand();
myCommand.CommandText = "Select * from " + tableName;
myCommand.CommandType = CommandType.Text;
myCommand.Connection = connString;
How to avoid sql injection ?
Just create a query with a real param and check for the existence of the tablename - somthing like:
SELECT COUNT(*) FROM SYS.TABLES WHERE NAME = #pYOURTABLENAME
IF that returns 1 then you know that the table exists and thus can use it in the SELECT you showed in the question...
However I strongly recommend to try anything to get rid of the need for any code prone to SQL injection!
I would ensure table name contains only these characters:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]. -_0123456789
E.g.,
Regex regex = new Regex(#"^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\[\]. -_0123456789]{1,128}$");
if (!regex.IsMatch(tableName)) throw new ApplicationException("Invalid table name");
To do a more comprehensive job including non-English languages see this reference on what a valid table names:
http://msdn.microsoft.com/en-us/library/ms175874.aspx
You need to verify that tableName is appropriate. After some sanity checking (making sure it has no spaces, or other disallowed characters for table names, etc), I would then first query the database for the names of all tables, and programmatically verify that it is one of those table names. Then proceed to run the query you show.
I'd look at moving the SQL to a stored proc and review this article by Erland Sommarskog as it has some great ideas for using dynamic SQL within stored procs. I'd certainly look into it. It discusses a lot of the issues around SQL injection and possible alternatives to dynamic SQL.
He also has another great article on ways to use arrays in stored procs. I know you didn't ask for that, but I often refer to these two articles as I think they are quite insightful and provide you with some useful ideas with regards to writing your procedures.
In addition to some of the suggestions linked above, I still have some basic parameter sanitisation mechanisms that I use if I am ever using dynamic SQL. An example of this is as follows;
IF LEN(#TableName) < 5 OR LEN(#TableDisplayName) < 5
BEGIN
RAISERROR('Please ensure table name and display name are at least 5 characters long', 16, 1)
END
IF NOT (#TableName not like '%[^A-Z]%')
BEGIN
RAISERROR('The TableName can only contain letters', 16, 1)
END
IF NOT (#TableDisplayName not like '%[^0-9A-Z ]%')
BEGIN
RAISERROR('The TableDisplayName can only contain letters, numbers or spaces', 16, 1)
END
This combined with using parameters within your dynamic sql and then executing using sp_executesql certainly help to minimise the possibility of a SQL injection attack.

How to escape simple SQL queries in C# for SqlServer

I use an API that expects a SQL string. I take a user input, escape it and pass it along to the API. The user input is quite simple. It asks for column values. Like so:
string name = userInput.Value;
Then I construct a SQL query:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
name.replace("'", "''"));
Is this safe enough? If it isn't, is there a simple library function that make column values safe:
string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
SqlSafeColumnValue(name));
The API uses SQLServer as the database.
Since using SqlParameter is not an option, just replace ' with '' (that's two single quotes, not one double quote) in the string literals. That's it.
To would-be downvoters: re-read the first line of the question. "Use parameters" was my gut reaction also.
EDIT: yes, I know about SQL injection attacks. If you think this quoting is vulnerable to those, please provide a working counterexample. I think it's not.
I was using dynamic sql (I can hear the firing squad loading their rifles) for search functionality, but it would break whenever a user searched for somebody with a surname like "O'Reilly".
I managed to figure out a work-around (read "hack"):
Created a scalar-valued function in sql that replaced a single quote with two single quotes, effectively escaping the offending single quote, so
"...Surname LIKE '%O'Reilly%' AND..."
becomes
"...Surname LIKE '%O''Reilly%' AND..."
This function gets invoked from within sql whenever I suspect fields could contain a single quote character ie: firstname, lastname.
CREATE FUNCTION [dbo].[fnEscapeSingleQuote]
(#StringToCheck NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #Result NVARCHAR(MAX)
SELECT #Result = REPLACE(#StringToCheck, CHAR(39), CHAR(39) + CHAR(39))
RETURN #Result
END
Not very elegant or efficient, but it works when you're in a pinch.
One may wish to replace ' with '' instead of parameterizing when needing to address the ' problem in a large amount of ad hoc sql in a short time with minimal risk of breakage and minimal testing.
SqlCommand and Entity Framework use exec sp_executesql....
So there really is an alternative to raw strings with your own escaping pattern presumably. With SqlCommand you are technically using parameterised queries but you're bypassing the ADO.Net abstraction of the underlying SQL code.
So while your code doesn't prevent SQL Injection, the ultimate answer is sp_executesql not SqlCommand.
Having said that, I'm sure there are special handling requirements for generating an SQL Injection-proof string which utilizes sp_executesql.
see: How to return values from a dynamic SQL Stored Procedure to the Entity Framework?
Simple:
const string sql = "SELECT * FROM SOME_TABLE WHERE Name = #name";
and add the #name parameter with value:
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#name", name);
If you need to escape a string for a MSSQL query try this:
System.Security.SecurityElement.Escape(Value)

SQL injection on INSERT

I have created a small survey web page on our company Intranet. This web page is not accessible from the outside.
The form is simply a couple of radio buttons and a comments box.
I would like to maintain good coding practices and would like to guard against SQL Injections.
Can SQL injections happen on a insert statement with comments from the textbox?
If so, how can I guard against it using .NET 2.0?
Injection can happen on any SQL statement not run properly.
For example, let's pretend your comment table has two fields, an integer ID and the comment string. So you'd INSERT as follows:
INSERT INTO COMMENTS VALUES(122,'I like this website');
Consider someone entering the following comment:
'); DELETE FROM users; --
If you just put the comment string into the SQL without any processesing this could turn your single INSERT in to the following two statements followed by a comment:
INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- ');
This would delete everything from your users table. And there are people willing to spend all day finding the right tablename to empty using trial and error and various tricks. Here's a description of how you could perform an SQL Injection attack.
You need to use parameterized SQL statements to prevent this.
And this isn't just for security reasons. For example, if you're creating your SQL statements naively the following comment:
I'm just loving this website
would cause an SQL syntax error because of the apostrophe being interpreted by SQL as a closing quote.
Use parameterized queries so that the text is automatically quoted for you.
SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (#val1,#val2,#txt)";
command.AddParameterWithValue( "val1", value1 );
command.AddParameterWithValue( "val2", value2 );
command.AddParameterWithValue( "txt", text );
...
SQL injection can happen any time you pass a query back to the database. Here's a simple demonstration:
SQL Injection Explained
The key, within .NET, is to do as Dave Webb has given. It will prevent the injection attempt by encompassing the entire string as one parameter to be submitted, handling all characters that might be interpreted by SQL Server to change the query or append additional commands.
And it should be pointed out that SQL injection can occur on any application, not just web applications. And that an internal attack is usually the most costly to an organization. One cannot safely assume that an attack won't originate from within.
In addition to using prepared statements and parameters rather than concatenating strings into your SQL you should also do the following:
Validate and format user input on the server side. Client side validation and limits can easily be bypasses with tools like WebScarab, or by spoofing your form.
Configure appropriate permissions for the database user account. Web application should use a separate account or role in your database with permissions restricted to only the tables, views and procedures required to run your application. Make sure that user does not have select rights on the system tables
Hide detailed error messages from users, and use less common names for your objects. It amazes me how often you can determine the server type (oracle, mysql, sqlserver) and find basic schema information in an error message and then get information from tables called 'user(s)', 'employee(s)'. If you haven't set your permissions as in (2) and I can determine your server type you are open to statements like this for SQL Server
SELECT table_name FROM information_schema.table
EXECUTE sp_help foundTableName
Yes, they can happen. The easiest way to guard against this is to use prepared statements rather than building the SQL manually.
So, rather than this:
String sql =
String.Format("INSERT INTO mytable (text_column) VALUES ( '{0}' )",
myTextBox.Text); // Unsafe!
You would do something like this:
String sql = "INSERT INTO mytable (text_column) VALUES ( ? )"; // Much safer
Then add the text of the text box as a parameter to your DbCommand which will cause it to be automatically escaped and replace the "?" in the SQL.
Prevent SQL Injection by using prepared statement. The use of placehoder(?) totally eliminates sql Injection Vulnerability.
example
String sql=Select * from user_table where username='+request.getparameter("username")+';
statement.executeQuery(sql);
the above statement is vulnerable to sql injection.
To make it safe against sql injection.
Use following the snippet
String sql=Select * from user_table where username=?;
statement.setString(1,username);
Yes, it can. Let's say the client sends this:
OR 1 = 1
That can be very painfull for your
SELECT * FROM admin WHERE name = #name AND password = #password
You can prevent this with
using Parameter class from ADO.NET
using regexp
reading, reading: http://www.codeproject.com/KB/database/SqlInjectionAttacks.aspx
The easiest way to guard against that form of SQL injection, is to use parameters and stored procedures rather then building sql statements to run. (In C# or internally to SQL Server).
However I'm not entirely sure you should be spending time on this, unless of course it's your corporate policy, as the chances of it ever occuring internally are minimal at best, and if it did occur, I would hope you would know immediately who it is.

Categories

Resources