Jeg vil ikke påstå at det er det endegyldige svar, men typisk er det via strengværdier du vil kunne opleve forsøg på SQL-injections, så derfor er det som udgangspunkt apostroffer (') der skal fjernes...
Jeg vil hellere anbefale dig at undersøge Command-objektet til parameteriserede SQL-sætninger, for det giver dig en god sikkerhed for at injections ikke kan udføres.
Eksempel:
dim id id = 1
dim cmd, rs
set cmd = Server.CreateObject("ADODB.Command") set cmd.ActiveConnection = conn ' conn er dit åbne connectionobjekt cmd.CommandType = adCmdText cmd.CommandText = "SELECT * FROM tabel1 WHERE id = ?" cmd.Parameters.Append cmd.CreateParameter("@id", adInteger, adParamInput, 4, id) set rs = cmd.Execute() ' ... og så hvad du ellers ville have gjort med dine data fra tabel1
Det er umiddelbart lidt mere omstændigt, men noget af det kan pakkes ind i en eller flere funktioner (f.eks. oprettelsen af commandobjektet og oprettelsen af parametre), så det bliver lidt lettere at have med at gøre. Hvis du vil vide mere om dette emne kan du jo sige til, så kan vi da debatere det lidt... :-)
Som nævnt tidligere, så er jeg ikke ekspert på SQL-injections, men den mest kendte metode til injections er at afslutte en streng og så lave noget SQL efter dette, som kan være mere eller mindre skadeligt for din database. Dette er i det mindste ikke muligt med Command-objektet ovenfor, da strengparametre af Command-objektet behandles som sådan, hvilket betyder at apostroffer blot bliver en naturlig del af parameterværdien og ikke som i strengsammensætningsscenariet en del af den samlede SQL-sætning.
Hvis man lige sætter sin fantasi lidt i spil kunne man forestille sig at en bruger forsøgt at indtaste flg. tekst i et felt (lad os kalde det feltet):
"'; DROP DATABASE;"
og det kunne jo være en katastrofe hvis den blev indsat i flg. SQL:
sql = "SELECT * FROM tabel1 WHERE felt = '" & feltet & "'"
Det ville så resultere i flg. SQL-sætning(er):
SELECT * FROM tabel1 WHERE felt = ''; DROP DATABASE;
Det er muligt at syntaksen for at slette en database er lidt anderledes, men idéen er vist tydelig nok.
Dette princip ville fungere på en SQL Server, hvorimod jeg er lidt mere usikker på om det ville gå i en Access-database (her ville siden højst sandsynligt ende med en fejl der fortæller en hacker lidt mere om din databases layout og måske endda placering).
Nu siger du (og mange andre) nok: "Jamen, det problem er jo løst hvis jeg gør som mitbrugernavn (og tusinde andre før ham/hende her på sitet)". Jeg synes dog det har sin berettigelse. Dels er det rarere at bruge et command-objekt, fordi det er mere i tråd med den COM-måde hvorpå ASP-objekter i øvrigt bruges, dels giver det nogle fordele i de tilfælde, hvor du skal lave batchopdateringer, da du kan genbruge samme Command-objekt og blot tildele nye parametre for hvert kald. Dette giver et performance-boost ifht. strengsammensætningsmotoden, hvor strengen skal sammensættes hver gang.
Desuden har Command-metoden en statisk kompleksitet, hvor strengsammensætningsmetoden har en tendens til at blive uoverskuelig, fordi der sprøjtes rundt med apostroffer, anførselstegn, ampersand'er og hvad har vi! :-)
Brug af parameters gør at SQL'en for-fortolkes, for så at vente på at modtage værdierne separat. Dermed er SQL injection umulig; uanset hvad der bliver sendt ind, vil det blive opfattet som en værdi, og ikke en del af SQL'en.
Dermed undgår du escaping - det er godt af to grunde: 1) Hvis du selv skriver en escaping funktion, så er det ikke sikkert du er klar over alle de tegn der kan være farlige (eks. NUL bytes) 2) Selvom du bruger databasens egne escaping funktioner, så er det stadig ikke 100% garanteret at der ikke kan opstå SQL injections - både MySQL og PostgreSQL havde for noget tid siden en fejl der escapede forkerte hvis bestemte tegnsæt og byte-komibinationer blev brugt.
Softspot: På en side bruger jeg nedenstående - vil du hjælpe mig med at få det til at passe til din løsning?
<% If isNumeric(intPage) = False Or intPage < 1 Then intPage = 1 Else intPage = Replace(intPage, "'", "") intPage = Replace(intPage, """", "") intPage = Replace(intPage, "<", "<") intPage = Replace(intPage, ">", ">") End If
Set ConnObj = Server.CreateObject("ADODB.Connection") DSN = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:/web/bruger/domain.dk/database/mindatabase.mdb" ConnObj.Open DSN
strSQL = "SELECT c_brugere5, c_portalniveau1, c_formular1 FROM sikkerhed WHERE sprog = '"& session("sprog") &"' and id = " & CLng(intPage) Set RstObj = ConnObj.Execute(strSQL)
Og husk: Selvom du bruger Command-objekter, så er det stadig vigtigt at validere data (typer og indhold) inden du kaster dem efter databasen (ligesom du gør med intPage).
I princippet ja, du vil typisk bare ikke modtage et recordset når du kalder cmd.execute().
Der er naturligvis mange flere muligheder for at bruge Command-objektet, f.eks. muligheden for at oprette returparametre, in-/outputparametre og rene outputparametre fra stored procedures. Dette er dog nok mest relevant når du arbejder med en "rigtig" database (f.eks. SQL Server) ;-)
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.