1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft SQL Server 2008 R2 Unleashed- P171 pptx

10 171 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 169,93 KB

Nội dung

ptg 1644 CHAPTER 43 Transact-SQL Programming Guidelines, Tips, and Tricks LISTING 43.1 Sample Procedure to Demonstrate SQL Injection use bigpubs2008 go create proc dbo.get_titles @type varchar(12) = null, @pubdate varchar(10) = null, @price varchar(6) = null, @title varchar(80) = null as declare @where varchar(4000) set @where = ‘ WHERE 1 = 1 ‘ if @type is not null set @where = @where + ‘ AND type = ‘’’ + @type + ‘’’’ if @pubdate is not null set @where = @where + ‘ AND pubdate = ‘’’ + @pubdate + ‘’’’ if @price is not null set @where = @where + ‘ AND price = ‘ + @price if @title is not null set @where = @where + ‘ AND title like ‘’’ + @title + ‘’’’ exec (‘select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles ‘ + @where) return Following is an example of a typical execution of this procedure if the end user enters business in the book type search field: exec dbo.get_titles @type = ‘business’ go title pubdate The Busy Executive’s Database Guide 06/12/2004 Cooking with Computers: Surreptitious Balance Sheets 06/09/2004 You Can Combat Computer Stress! 06/30/2004 Straight Talk About Computers 06/22/2004 To understand how to prevent SQL injection attacks, let’s look at a way that a hacker might attempt a SQL injection attack. What a hacker attempting a SQL injection attack might typically do with a web application is to seek out a search field and try to inject some SQL code into it to see if the application is susceptible to an attack. This would typi- cally be done by inserting a single quotation mark into the search field to close out the string and appending a SQL statement after it. For example, the hacker may enter the string ’ OR 1 = 1 into the search field. This search condition contains a single quota- tion mark and an end comment marker ( ). The quotation mark would have the effect of closing the search string, and the comment marker would comment out the rest of the query to prevent syntax errors caused by the SQL injection. The additional search condi- ptg 1645 General T-SQL Coding Recommendations 43 tion appended to the query would cause the query to return all rows from the table, and the hacker would know he’s found a susceptible text box: exec dbo.get_titles @title = ‘’’ OR 1 = 1 ’ go title pubdate Samuel Johnson 09/19/2008 Freud, Dora, and Vienna 1900 02/25/2008 Freud: A Life for Our Time 06/21/2008 For Love of the World 01/06/2006 Freud: A Life for Our Time 10/16/2007 The Riddle of Anna Anderson 02/21/2007 Final Analysis 05/31/2006 When the hacker sees the results of this query, he knows he’s found a susceptible text field and may try to query the system catalogs. Typically, this is done with a UNION ALL state- ment because the application would likely generate an error if multiple result sets were returned. With UNION, the hacker’s SQL injection statement would have to return the same number of columns as the original query, and the columns would need to be of compati- ble data types. It might take the hacker some trial and error, but eventually, he might come up with a query string such as UNION ALL select TABLE_NAME, NULL from INFORMATION_SCHEMA.TABLES to append to the following search value: exec dbo.get_titles @title = ‘’’ UNION ALL select TABLE_NAME, NULL from INFORMATION_SCHEMA.TABLES ’ go title pubdate sales_big NULL roysched NULL titleauthor NULL PARTS NULL titleview NULL publishers NULL top_sales NULL sales_archive NULL authors NULL jobs NULL ptg 1646 CHAPTER 43 Transact-SQL Programming Guidelines, Tips, and Tricks pub_info NULL sales NULL sales_qty_rollup NULL stores NULL titles NULL discounts NULL employee NULL sales_noclust NULL With this information, the hacker has a list of all the tables defined in the database. At this point, the hacker might try to probe deeper into the database to look for sensitive data. For example, the hacker might decide to try to query the authors table to see if there is any sensitive data, such as Social Security numbers, in it. To do so, the hacker would use a trial-and-error approach of entering various SQL injection queries against the system catalogs to get column information, possibly eventually coming up with the SQL injection statements used in the following queries: exec dbo.get_titles @title = ‘’’ UNION ALL select name, str(id) from sysobjects where name = ‘’authors’’ ’ go title pubdate authors 1253579504 exec dbo.get_titles @title = ‘’’ UNION ALL select name, null from syscolumns where id = 1253579504 ’ go title pubdate au_id NULL au_lname NULL au_fname NULL phone NULL address NULL city NULL state NULL zip NULL contract NULL At this point, the hacker has an idea what fields are in the authors table and could attempt to view data in those columns to try to uncover personal information such as Social Security numbers, credit card numbers, addresses, and so on: exec dbo.get_titles @title = ‘’’ UNION ALL select au_id + au_lname, au_fname from authors ’ ptg 1647 General T-SQL Coding Recommendations 43 go title pubdate 681-61-9588Ahlberg Allan 739-35-5165Ahlberg Janet 499-84-5672Alexander Lloyd 969-00-7063Amis Martin 263-46-4600Arendt Hannah 626-03-3836Arnosky Jim 432-31-3829Bate W. Jackson 437-99-3329Bauer Caroline Feller 378-33-9373Benchley Nathaniel 409-56-7008Bennet Abraham 648-92-1872Blotchet-Halls Reginald The hacker could continue the SQL injection attack by attempting to view data in other tables. Or, worse, he could attempt to destroy data by attempting updates, deletes, or inserts of his own data, or, even worse, truncate tables or drop tables entirely. Depending on the account that the application runs under and the rights assigned to that account, the hacker might even be able to run system stored procedures or extended stored proce- dures such as xp_cmdshell. So what can be done to help avoid SQL injection attacks? The best solution is to make sure the application itself performs validation on the user input fields to prevent the injection of SQL commands. Also, the application should keep any input fields as small as possible to reduce the likelihood of a hacker being able to squeeze SQL code into the field without it being truncated (which usually leads to a T-SQL syntax error). In addi- tion, there are precautions you can take in your databases and T-SQL code as a secondary mechanism to prevent SQL injection. On the database side, one thing you can do is to make sure the application runs under a user account with the minimal permissions necessary. You should avoid giving the appli- cation user account either dbo or, worse, sa permissions. (It’s frightening how many appli- cations are out there running under the dbo or sa account!) Restricting the permissions restricts the amount of damage a hacker might possibly inflict on a database. Another way you can help avoid SQL injection is to check for common SQL injection methods in your stored procedure code. For example, you could recode the procedure shown in Listing 43.1 to look for the UNION statement (one common method used in SQL injection attacks) and to strip out any text from an input string from the point where the UNION statement is found. Listing 43.2 shows an example of this. ptg 1648 CHAPTER 43 Transact-SQL Programming Guidelines, Tips, and Tricks LISTING 43.2 Stripping Out the UNION Clause to Help Avoid SQL Injection alter proc get_titles @type varchar(12) = null, @pubdate varchar(10) = null, @price varchar(6) = null, @title varchar(80) = null as declare @where varchar(4000), @query varchar(8000) set @query = ‘select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles ‘ set @where = ‘ WHERE 1 = 1 ‘ if @type is not null set @where = @where + ‘ AND type = ‘’’ + @type + ‘’’’ if @pubdate is not null set @where = @where + ‘ AND pubdate = ‘’’ + @pubdate + ‘’’’ if @price is not null set @where = @where + ‘ AND price = ‘ + @price if @title is not null set @where = @where + ‘ AND title like ‘’’ + @title + ‘’’’ The following statement truncates the @where clause at the point where it finds the UNION statement select @query = @query + left(@where, charindex(‘UNION’, @where) - 1) exec (@query) return When this query is executed, the UNION statement is stripped out. The WHERE clause ends up looking like the following: WHERE 1 = 1 AND title like ‘’ With the UNION stripped out, leaving only an empty string, the query now returns an empty result set: exec dbo.get_titles @title = ‘’’ UNION ALL select name,null from syscolumnswhere id = 1253579504 ’ title pubdate In addition to having the stored procedure code look for the UNION clause, you could further expand on this to look for other common SQL injection methods. One other, possibly more reliable, way to help avoid SQL injection attacks is to parameterize your dynamic queries by using sp_executesql. When you embed parameters in the dynamic SQL string rather than build it on the fly, it is much harder for a hacker to insert SQL statements into the dynamic query. Listing 43.3 shows an example of this approach. ptg 1649 General T-SQL Coding Recommendations 43 LISTING 43.3 Using sp_executsql to Help Avoid SQL Injection alter proc get_titles @type varchar(12) = null, @pubdate varchar(10) = null, @price varchar(6) = null, @title varchar(80) = null as declare @where nvarchar(2000), @query nvarchar(2000) set @query = ‘select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles ‘ set @where = ‘ WHERE 1 = 1 ‘ if @type is not null set @where = @where + ‘ AND type = @type ‘ if @pubdate is not null set @where = @where + ‘ AND pubdate = @pubdate ‘ if @price is not null set @where = @where + ‘ AND price = convert(money, @price) ‘ if @title is not null set @where = @where + ‘ AND title like @title ‘ Build the final query select @query = @query + @where exec sp_executesql @query, N’@type varchar(12), @pubdate varchar(10), @price varchar(6), @title varchar(80)’, @type, @pubdate, @price, @title return With this version of the procedure, the query that gets built looks like the following: select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles WHERE 1 = 1 AND title like @title With the query written this way, the value passed in for @title when sp_executesql is invoked is the following: ’’ UNION ALL select name, null from syscolumns where id = 1253579504 With this value passed in as the argument to the @title variable in the where clause, the search condition eventually becomes this: AND title like “‘’ UNION ALL select name, null from syscolumns where id = 1253579504 ” ptg 1650 CHAPTER 43 Transact-SQL Programming Guidelines, Tips, and Tricks As you might surmise, this string matches no actual titles in the titles tables, so an empty result set is returned. There is another alternative approach to preventing SQL injection attacks. Instead of searching for possible injection methods within the parameters used to build the query, you can make sure the dynamic SQL code fragments contain only allowable keywords and values. For example, consider a variation of the stored procedure in Listing 43.3 that allows for the specification of a dynamic sort on the query: alter proc get_titles @type varchar(12) = null, @pubdate varchar(10) = null, @price varchar(6) = null, @title varchar(80) = null, @sort varchar(1000) = ‘’ as declare @where nvarchar(2000), @query nvarchar(2000) set @query = ‘select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles ‘ set @where = ‘ WHERE 1 = 1 ‘ if @type is not null set @where = @where + ‘ AND type = @type ‘ if @pubdate is not null set @where = @where + ‘ AND pubdate = @pubdate ‘ if @price is not null set @where = @where + ‘ AND price = convert(money, @price) ‘ if @title is not null set @where = @where + ‘ AND title like @title ‘ Build the final query select @query = @query + @where + case when @sort <> ‘’ then ‘ORDER BY ‘ + @sort else ‘’ end exec sp_executesql @query, N’@type varchar(12), @pubdate varchar(10), @price varchar(6), @title varchar(80)’, @type, @pubdate, @price, @title Return Although the use of parameterized SQL with sp_executesql avoids issues with SQL injec- tion via the @type, @pubdate, @price, and @title parameters, the code opens itself up again to SQL injection with the @sort variable being tacked onto the end of the query. Instead of trying to find all the possible commands that could be embedded in the @sort variable, and alternative approach is to make sure it contains only allowable keywords and ptg 1651 General T-SQL Coding Recommendations 43 columns. The ORDER BY clause is reasonably simple; the only allowable values are the keywords DESC and ASC, column position numbers, and column names. In this example, you set up the code in the procedure to allow only the DESC and ASC keywords and a limited set of column names. The code strips out all the allowable values, and if anything else is left, you know that the @sort parameter contains something that it shouldn’t and can disallow it. An example using this approach is shown in Listing 43.4. LISTING 43.4 Checking for Only Allowable Values to Prevent SQL Injection alter proc get_titles @type varchar(12) = null, @pubdate varchar(10) = null, @price varchar(6) = null, @title varchar(80) = null, @sort varchar(1000) = ‘’ as declare @where nvarchar(2000), @query nvarchar(2000) , @sort_check varchar(1000) set @query = ‘select left(title, 60) as title, convert (char(10), pubdate, 101) as pubdate from dbo.titles ‘ Replace all allowable terms/syntax in @sort with empty strings Allowable terms are ASC, DESC, title, pubdate, price, type and comma (,) Set @sort_check = replace(@sort, ‘ASCENDING’, ‘’) Set @sort_check = replace(@sort_check, ‘DESCENDING’, ‘’) Set @sort_check = replace(@sort, ‘ASC’, ‘’) Set @sort_check = replace(@sort_check, ‘DESC’, ‘’) Set @sort_check = replace(@sort_check, ‘,’, ‘’) Set @sort_check = replace(@sort_check, ‘title’, ‘’) Set @sort_check = replace(@sort_check, ‘pubdate’, ‘’) Set @sort_check = replace(@sort_check, ‘price’, ‘’) Set @sort_check = replace(@sort_check, ‘type’, ‘’) If @sort_check <> ‘’ the @sort column contains a disallowed term Begin Raiserror (‘Invalid sort specified’, 16, 1) Return -101 end set @where = ‘ WHERE 1 = 1 ‘ if @type is not null set @where = @where + ‘ AND type = @type ‘ if @pubdate is not null set @where = @where + ‘ AND pubdate = @pubdate ‘ if @price is not null ptg 1652 CHAPTER 43 Transact-SQL Programming Guidelines, Tips, and Tricks set @where = @where + ‘ AND price = convert(money, @price) ‘ if @title is not null set @where = @where + ‘ AND title like @title ‘ Build the final query select @query = @query + @where + case when @sort <> ‘’ then ‘ORDER BY ‘ + @sort Else ‘’ end exec sp_executesql @query, N’@type varchar(12), @pubdate varchar(10), @price varchar(6), @title varchar(80)’, @type, @pubdate, @price, @title return go execute with a valid @sort value exec get_titles @pubdate = ‘2/21/2007’, @sort = ‘type ASC, price DESC’ execute with an attempted SQL injection in @sort parameter exec get_titles @pubdate = ‘2/21/2007’, @sort = ‘type ASC, price DESC; select * from sysobjects’ go title pubdate The Riddle of Anna Anderson 02/21/2007 Zuckerman Unbound 02/21/2007 Later the Same Day 02/21/2007 (3 row(s) affected) Msg 50000, Level 16, State 1, Procedure get_titles, Line 26 Invalid sort specified Dynamic SQL is a great feature in SQL Server that provides considerable flexibility in building queries in stored procedures. However, it also presents a risk if you are not careful to prevent possible SQL injection attacks. Comment Your T-SQL Code Anyone who has ever had to review or change some code recognizes the importance of comments. Even if it seems obvious what the code does when you’re writing it, the meaning will most certainly not be as obvious later, especially if someone other than the original author is looking at it. ptg 1653 General T-SQL Performance Recommendations 43 When you are working with large code blocks, a good technique to follow is to add a comment at the beginning and end of the code block: while ( ) /* Begin loop1 */ begin end /* End loop1 */ if (@price > 1) /* if (@price > 1) */ begin end /* if (@price > 1) */ Another recommendation is to include a comment header at the beginning of compiled objects such as stored procedures, functions, and triggers. Following is a sample comment header you might want to use as a template: /*********************************************************/ Procedure Name: p_proc_name Purpose: Describe the purpose of the procedure here. Include any special notes on usage or code logic Input Parameters: @param1 numeric(12,0) Not Required @param2 tinyint Not required Output Parameters: None Return Values: 0 Success Other Error Written By: Joe Developer, 7/1/08 Modified By: Joe Developer, 7/5/08 Describe changes made to the proc here Reviewed By: /*************************************************************/ General T-SQL Performance Recommendations How you write T-SQL queries can often have an effect on the performance of those queries. The following sections provide some general guidelines to keep in mind to help ensure that you are getting optimal performance from your queries. . ptg 1644 CHAPTER 43 Transact -SQL Programming Guidelines, Tips, and Tricks LISTING 43.1 Sample Procedure to Demonstrate SQL Injection use bigpubs2008 go create proc dbo.get_titles @type. 06/22/2004 To understand how to prevent SQL injection attacks, let’s look at a way that a hacker might attempt a SQL injection attack. What a hacker attempting a SQL injection attack might typically. = ‘’’ OR 1 = 1 ’ go title pubdate Samuel Johnson 09/19 /2008 Freud, Dora, and Vienna 1900 02/25 /2008 Freud: A Life for Our Time 06/21 /2008 For Love of the World 01/06/2006 Freud: A Life for Our

Ngày đăng: 05/07/2014, 02:20