Coding techniques for protecting against Sql injection
2010-03-30 15:18
351 查看
OverthepastfewweekstherehavebeenreportsandcommentaryaboutSQLinjectionattacksbeinglaunchedagainstbothclassicASPandASP.NETsites(somedetailsathttp://blogs.iis.net/bills/archive/2008/04/26/sql-injection-attacks-on-iis-web-servers.aspx).
IncludedinthispostareVB.NETandC#samplesthatcanbeusedtoscreenincomingquery-string,formandcookievaluesforpotentialSqlinjectionvalues.Howeverbecausevalidinputdatavariesfromwebsitetowebsite,itisnotpossibletowriteaone-size-fits-allscreeningmechanism.Youcanmodifythesamplecodeincludedinthisposttotightenorloosenthecharactersequencesasappropriateforyourwebsite.
Alsoasareminder,ifawebsitemakesheavyuseofdynamicallyconstructedSql(asopposedtoparameterizedSqlorparameterizedstoredprocedures)itisabestpracticetoescapeallsinglequotescontainedinun-trustedwebinput.SinceitisnotpossibletomakethisreplacementusingtheHttpModule/BeginRequestapproachesshownbelow,youcaninsteadscrubawebsite'scodeandperformtheescapinginallplaceswheredynamicSqlisbeingbuilt.
IncludedinthispostareVB.NETandC#samplesthatcanbeusedtoscreenincomingquery-string,formandcookievaluesforpotentialSqlinjectionvalues.Howeverbecausevalidinputdatavariesfromwebsitetowebsite,itisnotpossibletowriteaone-size-fits-allscreeningmechanism.Youcanmodifythesamplecodeincludedinthisposttotightenorloosenthecharactersequencesasappropriateforyourwebsite.
Alsoasareminder,ifawebsitemakesheavyuseofdynamicallyconstructedSql(asopposedtoparameterizedSqlorparameterizedstoredprocedures)itisabestpracticetoescapeallsinglequotescontainedinun-trustedwebinput.SinceitisnotpossibletomakethisreplacementusingtheHttpModule/BeginRequestapproachesshownbelow,youcaninsteadscrubawebsite'scodeandperformtheescapinginallplaceswheredynamicSqlisbeingbuilt.
//C#snippetprivatestringSafeSqlLiteral(stringinputSQL)[/code]
{
returninputSQL.Replace("'","''");
}
'VB.NETsnippet
PrivateFunctionSafeSqlLiteral(ByValinputSQLAsString)AsString
ReturninputSQL.Replace("'","''")
EndFunction
ASP.NET2.0VB.NET
Youcanscreenallincomingquery-string,formandcookievaluesbyrunningcodeduringtheBeginRequestevent.ThistypeofcodecanrunoneveryrequestwhenimplementedinanHttpModule.ThesamplecodebelowdefinesanHttpModuleintheApp_Codedirectory,andthenregistersthemoduleinweb.configsothatitrunsoneveryrequest.Thesamplecodewillcheckincomingdataandautomaticallyredirecttoapagecalled"Error.aspx"ifsuspiciouscharactersequencesarefound.Firstcreateanewfileinyoursite'sApp_CodedirectorycalledSampleSqlInjectionScreeningModule.vb.Thenpastethefollowingcodeintothefile:
ImportsMicrosoft.VisualBasic
NamespaceSample
PublicClassSampleSqlInjectionScreeningModuleVB
ImplementsIHttpModule
'Definesthesetofcharactersthatwillbechecked.
'Youcanaddtothislist,orremoveitemsfromthislist,asappropriateforyoursite
PublicSharedblackListAsString()={"--",";--",";","/*","*/","@@",_
"@","char","nchar","varchar","nvarchar","alter",_
"begin","cast","create","cursor","declare","delete",_
"drop","end","exec","execute","fetch","insert",_
"kill","open","select","sys","sysobjects","syscolumns",_
"table","update"}
PublicSubDispose()ImplementsIHttpModule.Dispose
'no-op
EndSub
'TellsASP.NETthatthereiscodetorunduringBeginRequest
PublicSubInit(ByValappAsHttpApplication)ImplementsIHttpModule.Init
AddHandlerapp.BeginRequest,AddressOfapp_BeginRequest
EndSub
'Foreachincomingrequest,checkthequery-string,formandcookievaluesforsuspiciousvalues.
PrivateSubapp_BeginRequest(ByValsenderAsObject,ByValeAsEventArgs)
DimRequestAsHttpRequest=TryCast(sender,HttpApplication).Context.Request
ForEachkeyAsStringInRequest.QueryString
CheckInput(Request.QueryString(key))
Next
ForEachkeyAsStringInRequest.Form
CheckInput(Request.Form(key))
Next
ForEachkeyAsStringInRequest.Cookies
CheckInput(Request.Cookies(key).Value)
Next
EndSub
'Theutilitymethodthatperformstheblacklistcomparisons
'Youcanchangetheerrorhandling,anderrorredirectlocationtowhatevermakessenseforyoursite.
PrivateSubCheckInput(ByValparameterAsString)
ForiAsInteger=0ToblackList.Length-1
If(parameter.IndexOf(blackList(i),StringComparison.OrdinalIgnoreCase)>=0)Then
'
'HandlethediscoveryofsuspiciousSqlcharactershere
'
'genericerrorpageonyoursite
HttpContext.Current.Response.Redirect("~/Error.aspx")
EndIf
Next
EndSub
EndClass
EndNamespace
YouthenneedtoregistertheHttpModulewithASP.NET.
IfyouarerunningASP.NET2.0onIIS6,orASP.NET2.0onIIS7inClassicMode,placetheboldedmoduleregistrationshownbelowinsideofthesystem.web/httpModulessection:
<system.web>
…
<httpModules>
…
<addname="SampleSqlInjectionScreeningModuleVB"type="Sample.SampleSqlInjectionScreeningModuleVB"/>
…
</httpModules>
…
</system.web>
HoweverifyouarerunningASP.NET2.0onIIS7inIntegratedMode,youinsteadneedtoplacetheboldedmoduleregistrationshownbelowinsideofthesystem.webServer/modulessection:
<system.webServer>
…
<modules>
…
<addname="SampleSqlInjectionScreeningModuleVB"type="Sample.SampleSqlInjectionScreeningModuleVB"preCondition="managedHandler"/>
…
</modules>
…
</system.webServer>
ASP.NET2.0C#
Youcanscreenallincomingquery-string,formandcookievaluesbyrunningcodeduringtheBeginRequestevent.ThistypeofcodecanrunoneveryrequestwhenimplementedinanHttpModule.ThesamplecodebelowdefinesanHttpModuleintheApp_Codedirectory,andthenregistersthemoduleinweb.configsothatitrunsoneveryrequest.Thesamplecodewillcheckincomingdataandautomaticallyredirecttoapagecalled"Error.aspx"ifsuspiciouscharactersequencesarefound.Firstcreateanewfileinyoursite'sApp_CodedirectorycalledSampleSqlInjectionScreeningModule.cs.Thenpastethefollowingcodeintothefile:
usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.HtmlControls;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Xml.Linq;
namespaceSample
{
publicclassSampleSqlInjectionScreeningModuleCS:IHttpModule
{//Definesthesetofcharactersthatwillbechecked.
//Youcanaddtothislist,orremoveitemsfromthislist,asappropriateforyoursite
publicstaticstring[]blackList={"--",";--",";","/*","*/","@@","@",
"char","nchar","varchar","nvarchar",
"alter","begin","cast","create","cursor","declare","delete","drop","end","exec","execute",
"fetch","insert","kill","open",
"select","sys","sysobjects","syscolumns",
"table","update"};
publicvoidDispose(){
//no-op
}
//TellsASP.NETthatthereiscodetorunduringBeginRequest
publicvoidInit(HttpApplicationapp)
{
app.BeginRequest+=newEventHandler(app_BeginRequest);
}
//Foreachincomingrequest,checkthequery-string,formandcookievaluesforsuspiciousvalues.
voidapp_BeginRequest(objectsender,EventArgse)
{
HttpRequestRequest=(senderasHttpApplication).Context.Request;
foreach(stringkeyinRequest.QueryString)
CheckInput(Request.QueryString[key]);
foreach(stringkeyinRequest.Form)
CheckInput(Request.Form[key]);
foreach(stringkeyinRequest.Cookies)
CheckInput(Request.Cookies[key].Value);
}
//Theutilitymethodthatperformstheblacklistcomparisons
//Youcanchangetheerrorhandling,anderrorredirectlocationtowhatevermakessenseforyoursite.
privatevoidCheckInput(stringparameter)
{
for(inti=0;i<blackList.Length;i++)
{
if((parameter.IndexOf(blackList[i],StringComparison.OrdinalIgnoreCase)>=0))
{
//
//HandlethediscoveryofsuspiciousSqlcharactershere
//
HttpContext.Current.Response.Redirect("~/Error.aspx");//genericerrorpageonyoursite
}
}
}
}
}
YouthenneedtoregistertheHttpModulewithASP.NET.
IfyouarerunningASP.NET2.0onIIS6,orASP.NET2.0onIIS7inClassicMode,placetheboldedmoduleregistrationshownbelowinsideofthesystem.web/httpModulessection:
<system.web>
…
<httpModules>
…
<addname="SampleSqlInjectionScreeningModuleCS"type="Sample.SampleSqlInjectionScreeningModuleCS"/>
…
</httpModules>
…
</system.web>
HoweverifyouarerunningASP.NET2.0onIIS7inIntegratedMode,youinsteadneedtoplacetheboldedmoduleregistrationshownbelowinsideofthesystem.webServer/modulessection:
<system.webServer>
…
<modules>
…
<addname="SampleSqlInjectionScreeningModuleCS"type="Sample.SampleSqlInjectionScreeningModuleCS"preCondition="managedHandler"/>
…
</modules>
…
</system.webServer>
ASP.NET1.1VB.NET
Youcanscreenallincomingquery-string,formandcookievaluesbyrunningcodeduringtheBeginRequestevent.Acentrallocationtoregisterthiscodeisinawebsite'sglobal.asaxfile.Thesamplecodebelowwillcheckincomingdataandautomaticallyredirecttoapagecalled"Error.aspx"ifsuspiciouscharactersequencesarefound.Firstyouwillneedtoaddanewnamespaceimportatthetopofyourglobal.asaxfile:
<%@Importnamespace="System.Globalization"%>
Nextplacethefollowingvariabledefinitionandprivatefunctionsomewhereinyourglobal.asaxfilebetweenthe<script>tags:
'Definesthesetofcharactersthatwillbechecked.
'Youcanaddtothislist,orremoveitemsfromthislist,asappropriateforyoursite
PublicSharedblackListAsString()={"--",";--",";","/*","*/","@@",_
"@","char","nchar","varchar","nvarchar","alter",_
"begin","cast","create","cursor","declare","delete",_
"drop","end","exec","execute","fetch","insert",_
"kill","open","select","sys","sysobjects","syscolumns","table",_
"update"}
'Theutilitymethodthatperformstheblacklistcomparisons
'Youcanchangetheerrorhandling,anderrorredirectlocationtowhatevermakessenseforyoursite.
PrivateSubCheckInput(ByValparameterAsString)
DimcomparerAsCompareInfo=CultureInfo.InvariantCulture.CompareInfo
ForiAsInteger=0ToblackList.Length-1
If(comparer.IndexOf(parameter,blackList(i),CompareOptions.IgnoreCase)>=0)Then
'
'HandlethediscoveryofsuspiciousSqlcharactershere
'
'genericerrorpageonyoursite
Response.Redirect("~/Error.aspx")
EndIf
Next
EndSub
Lastlyplacethefollowingfunctiondefinitionsomewhereinyourglobal.asaxfilebetweenthe<script>tags.ThisisthefunctiondefinitionthattellsASP.NETtorunstringchecksduringtheBeginRequestevent.Ifyourglobal.asaxfilealreadyhasafunctioncalledApplication_BeginRequest,youshouldinsteadplacethecontentsofthefunctiondefinitionbelowintoyourexistingversionofApplication_BeginRequest.
'Definesthesetofcharactersthatwillbechecked.
'Youcanaddtothislist,orremoveitemsfromthislist,asappropriateforyoursite
PublicSharedblackListAsString()={"--",";--",";","/*","*/","@@",_
"@","char","nchar","varchar","nvarchar","alter",_
"begin","cast","create","cursor","declare","delete",_
"drop","end","exec","execute","fetch","insert",_
"kill","open","select","sys","sysobjects","syscolumns","table",_
"update"}
'Theutilitymethodthatperformstheblacklistcomparisons
'Youcanchangetheerrorhandling,anderrorredirectlocationtowhatevermakessenseforyoursite.
PrivateSubCheckInput(ByValparameterAsString)
DimcomparerAsCompareInfo=CultureInfo.InvariantCulture.CompareInfo
ForiAsInteger=0ToblackList.Length-1
If(comparer.IndexOf(parameter,blackList(i),CompareOptions.IgnoreCase)>=0)Then
'
'HandlethediscoveryofsuspiciousSqlcharactershere
'
'genericerrorpageonyoursite
Response.Redirect("~/Error.aspx")
EndIf
Next
EndSub