Why does parameterized query prevent SQL Injection? (1)

Source: Internet
Author: User
Tags what sql

Many people know that SQL injection and SQL parametric query can prevent SQL injection, but not many know why it can prevent injection.

This article focuses on this issue. You may have seen this article in some articles. Of course, it is okay to check it.

First, we need to understand what SQL does after receiving a command:

For details, refer to the article: how to compile, recompile, and reuse execution plans of SQL Server.

Here, I simply say:Receive commands-> compile SQL to generate an execution plan-> select an execution plan-> execute an execution plan.

The specific steps may be different, but the general steps are shown above.

Next, let's analyze why the risk of SQL injection is caused by splicing SQL strings?

First create a table Users:

 
 
  1. CREATE TABLE [dbo].[Users](  
  2.  
  3. [Id] [uniqueidentifier] NOT NULL,  
  4.  
  5. [UserId] [int] NOT NULL,  
  6.  
  7. [UserName] [varchar](50) NULL,  
  8.  
  9. [Password] [varchar](50) NOT NULL,  
  10.  
  11.  CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED   
  12.  
  13. (  
  14.  
  15. [Id] ASC 
  16.  
  17. )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]  
  18.  
  19. ) ON [PRIMARY] 

Insert some data:

 
 
  1. INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),1,'name1','pwd1');  
  2. INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),2,'name2','pwd2');  
  3. INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),3,'name3','pwd3');  
  4. INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),4,'name4','pwd4');  
  5. INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),5,'name5','pwd5'); 

Suppose we have a user login page, the Code is as follows:

The SQL statement used to verify user logon is as follows:

 
 
  1. select COUNT(*) from Users where Password = 'a' and UserName = 'b'  

This code returns the number of users that both Password and UserName match. If it is greater than 1, it indicates that the user exists.

This article does not discuss password policies in SQL, nor code standards, mainly about why SQL injection can be prevented. Please do not tangle with some code or topics unrelated to SQL injection.

The execution result is displayed:

This is the SQL statement tracked by the SQL profile.

The injection code is as follows:

 
 
  1. select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1—' 

Here, someone sets UserName"B 'or 1 = 1 -".

The actual executed SQL statement is changed to the following:

We can see that SQL injection is successful.

Many people knowParameterized QueryThe above injection problems can be avoided, such as the following code:

 
 
  1. Class Program
  2. {
  3. Private static string connectionString = "Data Source =.; Initial Catalog = Test; Integrated Security = True ";
  4.  
  5. Static void Main (string [] args)
  6. {
  7. Login ("B", "");
  8. Login ("B 'or 1 = 1 --", "");
  9. }
  10.  
  11. Private static void Login (string userName, string password)
  12. {
  13. Using (SqlConnection conn = new SqlConnection (connectionString ))
  14. {
  15. Conn. Open ();
  16. SqlCommand comm = new SqlCommand ();
  17. Comm. Connection = conn;
  18. // Add a parameter for each piece of data
  19. Comm. CommandText = "select COUNT (*) from Users where Password = @ Password and UserName = @ UserName ";
  20. Comm. Parameters. AddRange (
  21. New SqlParameter [] {
  22. New SqlParameter ("@ Password", SqlDbType. VarChar) {Value = password },
  23. New SqlParameter ("@ UserName", SqlDbType. VarChar) {Value = userName },
  24. });
  25.  
  26. Comm. ExecuteNonQuery ();
  27. }
  28. }
  29. }

The actual executed SQL statement is as follows:

 
 
  1. exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(1)',@Password='a',@UserName='b' 
  2.  
  3. exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(11)',@Password='a',@UserName='b'' or 1=1—' 

We can see that parameterized queries mainly do these things:

1: filter parameters. You can see @ UserName = 'B' or 1 = 1 -'

2: execution plan reuse

Because execution plans are reused, SQL injection can be prevented.

First, analyze the nature of SQL injection,

The user writes an SQL statement to indicate that the query password is a and the user name is the number of all users of B.

By injecting an SQL statement, this SQL statement indicates the number of all users (the password is a and the user name is B) or 1 = 1.

We can see that the meaning of SQL has changed. Why ?, Because the previous execution plan was not reused, the injected SQL statement was re-compiled because the Syntax Parsing was re-executed. Therefore, to ensure that the SQL semantics remains unchanged, that is, the execution plan should be reused if I want to express SQL.

If execution plans cannot be reused, there is a risk of SQL injection, because the meaning of SQL statements may change, and the expressed query may change.

You can use the following script to query execution plans in SQL Server:

 
 
  1. DBCC FreeProccache
  2.  
  3. Select total_elapsed_time/execution_count average time, total_logical_reads/execution_count logical read,
  4. Usecounts reuse times, SUBSTRING (d. text, (statement_start_offset/2) + 1,
  5. (CASE statement_end_offset
  6. WHEN-1 then datalength (text)
  7. ELSE statement_end_offset END
  8. -Statement_start_offset)/2) + 1) execute the statement from sys. dm_exec_cached_plans
  9. Cross apply sys. dm_exec_query_plan (a. plan_handle) c
  10. , Sys. dm_exec_query_stats B
  11. Cross apply sys. dm_exec_ SQL _text (B. SQL _handle) d
  12. -- Where a. plan_handle = B. plan_handle and total_logical_reads/execution_count> 4000
  13. Order by total_elapsed_time/execution_count DESC;

Blog has an article: SQL Server parameterized query where in and like implementation


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.