Let us understand SQL injection attack, with an example. I have an Employee Search Page as shown in the image below. This webform has a very simple functionality. You enter the ID of the employee, you want to search and click the Search Employee button. If a match is found in the database, we show the employee record in the GridView.
Here is a youtube video that I have recorded on SQL Injection. Hope, you will find it useful.
The HTML for the Employee Serach Page is shown below. As you can see from the HTML, the Employee Serach Page contains TextBox, Button and a GridView control.
The codebehind page for the EmployeeSearchPage is shown below.
The Button1_Click event handler has the required ADO.NET code to get data from the database. This code is highly susceptible to sql injection attack and I will never ever have code like this in production environment. The second line in Button1_Click event handler, dynamically builds the sql query by concatenating the Employee ID that we typed into the TextBox.
So, for example, if we had typed 2 into the Employee ID textbox, we will have a SQL query as shown below.
Select * from Employees where Id=2
If a malicious user, types something like 2; Delete from Employees into the TextBox, then we will have a SQL query as shown below.
Select * from Employees where Id=2; Delete from Employees
When this query is executed, we loose all the data in the Employees table. This is SQL Injection Attack, as the user of the application is able to inject SQL and get it executed against the database. It is very easy to avoid SQL Injection attacks by using either parameterized queries or using stored procedures.
You may be thinking, how will the user of the application know the name of the table. Well, one way is to simply guess or inject a sql syntax error. The injected SQL syntax error causes the page to crash and can possibly reveal the name of the table as shown below. However, proper exception handling and custom error pages can be used to prevent the end user from seeing the yello screen of death. The screen shot below shows the table name Employees.
To solve SQL injection attack, create a Stored Procedure as shown below.
Create Procedure spGetEmployees
@Id int
as
Begin
Select * from Employees where Id=@Id
End
Modify the codebehind page for the EmployeeSearchPage, to use the stored procedure as shown below
Employee Search Page |
Here is a youtube video that I have recorded on SQL Injection. Hope, you will find it useful.
The HTML for the Employee Serach Page is shown below. As you can see from the HTML, the Employee Serach Page contains TextBox, Button and a GridView control.
Employee Search Page HTML |
The codebehind page for the EmployeeSearchPage is shown below.
Employee Search Page Code Behind |
The Button1_Click event handler has the required ADO.NET code to get data from the database. This code is highly susceptible to sql injection attack and I will never ever have code like this in production environment. The second line in Button1_Click event handler, dynamically builds the sql query by concatenating the Employee ID that we typed into the TextBox.
So, for example, if we had typed 2 into the Employee ID textbox, we will have a SQL query as shown below.
Select * from Employees where Id=2
If a malicious user, types something like 2; Delete from Employees into the TextBox, then we will have a SQL query as shown below.
Select * from Employees where Id=2; Delete from Employees
When this query is executed, we loose all the data in the Employees table. This is SQL Injection Attack, as the user of the application is able to inject SQL and get it executed against the database. It is very easy to avoid SQL Injection attacks by using either parameterized queries or using stored procedures.
You may be thinking, how will the user of the application know the name of the table. Well, one way is to simply guess or inject a sql syntax error. The injected SQL syntax error causes the page to crash and can possibly reveal the name of the table as shown below. However, proper exception handling and custom error pages can be used to prevent the end user from seeing the yello screen of death. The screen shot below shows the table name Employees.
Page crash revealing Employees table name |
To solve SQL injection attack, create a Stored Procedure as shown below.
Create Procedure spGetEmployees
@Id int
as
Begin
Select * from Employees where Id=@Id
End
Modify the codebehind page for the EmployeeSearchPage, to use the stored procedure as shown below
using System; using System.Data; using System.Data.SqlClient; namespace TestWeb { public partial class EmployeeSearch : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void Button1_Click(object sender, EventArgs e) { // Create the SQL Connection object. SqlConnection con = new SqlConnection ("server=localhost; database=TestDB; integrated security=SSPI"); // Create the SQL command object. Pass the stored procedure name // as a parameter to the constructor of the SQL command class SqlCommand cmd = new SqlCommand("spGetEmployees", con); // Create the SQL parameter object, specifying the name and the value // we want to pass to the SP. SqlParameter paramId = new SqlParameter("@Id", txtEmployeeId.Text); // Associate the Id parameter object with the command object, using // parameters collection property of the SQL Command object. cmd.Parameters.Add(paramId); // Specify the command type as stored procedure. This tells the command // object, that the command is a SQL stored procedure and not an adhoc sql query cmd.CommandType = CommandType.StoredProcedure; // Open the connection con.Open(); // Execute the command and assign the returned results as the data source for // the employyes girdview gvEmployees.DataSource = cmd.ExecuteReader(); // Call the DataBind() method, to bind the results to the employees grid view control gvEmployees.DataBind(); // Finally close the sql server connection object con.Close(); } } } |
You haven't mentioned the exact ways to avoid the situation. It would be great if you could explain it in detail.
ReplyDeleteUse stored procedure instead of plain sql query in code.
DeleteIn a way, he did, if you have a proper handling of the exception then you won't show an error like, exposing table names. One easy way, is imply wrap around the answer , in this case 2 with single quotes. that way is different this:
ReplyDeleteselect * from Employees where ID = 2;delete from Employees, than select * from Employees where ID = '2;delete from Employees'. The second one will generate an error that you can capture.
yep i also want an explaination that how to avoid it by showing eg through queries.
ReplyDeletepleas explaine how to solve this problem
ReplyDeleteThe solution is that we need to think as if we are tester and try to code according to ppl who may write such a kind of things. The better way is to always use store procs and fucntions to get values from database.
ReplyDeleteMay be we can control that from the text box level, by avoiding the user to enter special characters or curtail the length of the textbox ! Or else u check for the validity of the query too ! Yes agree with all of you. He should have shown an example to avoid this.
ReplyDeleteFor those who asked for a solution, he mentions it "It is very easy to avoid SQL Injection attacks by using either parameterized queries or using stored procedures."
ReplyDeleteAlways, always, always use stored procedures. This not only helps stop a SQL injection attack, it also encapsulates the SQL in the database and not in the web site code. Additionally security can be placed against that SP further prevent unauthorized execution.
You can also implement javascript to validate the input for the form field to prevent another vector of attack.
Very much interesting Materail
ReplyDeletenice explanation.i would happy if provide eg of how to avoid error by ussing procesures.i m expecting u will append soon
ReplyDeleteits a very nice blog
ReplyDeleteits a very nice blog
ReplyDeleteFor a comprehensive approach to security, multiple layers are the best bet, and approaching the best practice:
ReplyDelete1. Asking for the id (primary key) for the input is questionable. Some other input is perferrable.
2. Javascript/Jquery validation of the input is a good way of stopping problems at the client, before reaching the server. In this case, validating the string as a whole integer of a certain range (ie, 1 to 9999).
3. Utilization of stored procedures.
4. Fully specify the sql query (ie, "Select fname, lname from employees where lname like " + lname + "%", instead of "select *..."
5. Put the connection string somewhere else, other than directly in the code. An encrypted config file is a valid choice.
Oh, missed this one:
ReplyDeleteValidate input on the server side, as well. In this case, insuring you have a numeric value in the proper range (ie, 1 to 99999) before executing the sql code (hopefully in a stored procedure) is good practice
This is an employee search page and not a CRUD. so just have a select grant for the user. No delete or update grants. always validate the controls at the client site to avoid unnecessary round trips of post backs.
ReplyDeleteIn addition to previous advices, you can also use user with read-only access for select queries.
ReplyDeletenice
ReplyDeleteSQl injection attack can easily be done on such a codes where we are exposing the query for eg 'Select * from table_name where id = 2'. We can avoid this either by good exception handling or writing stored procedures even for such small queries. Passing the stored procedure will not allow the malicious user to manipulate the queries .
ReplyDeleteUsing stored procedures even for small queries like in the above example is very good practice to avoid sql injection attacks. The malicious user won't be able to manipulate the query inside the stored procedure. good Exception handling can also avoid sql injection attacks to an extent.
ReplyDeleteSimple way to solve the sql injection problem is to set the text-box max length property. The above method is also excellent. It is jst for this case only otherwise stored procedure is best.
ReplyDeleteThanks good work. Very simple and clean.
ReplyDeleteAnother way to avoid sql injection is to rip off special characters or disallow special characters from incoming values before passing values to query string
ReplyDeleteCuuld anyone please explain how to avoid page crash like that so that we can easily implement the logic
ReplyDeleteIn simple case like above use parameterized query
ReplyDeleteSelect * from employees where id={0},id
And also use client and server side validation for text box
Does SQL Injection possible in desktop application
ReplyDeletebest way is to validate the field on the form, whether it should only accept integer or if accept string then strip out the character ';' and also handle sql error properly.
ReplyDeletefor posting from a query string not from a form, make sure the query string does not contain character ';' before parse the query string into variables
@VenkatSir...Video explain a lot BRilliant...May b i m Too Late To get Your Tutorial...but you are Briliant
ReplyDelete