Jag har börjat på en funtion mot sql Injections tänkte ni kunde testa den och komma med förslag och förbättringar...
Function FixSQLInjection(ByVal SQL As String) As String
SQL = Trim(SQL)
Select Case 1
Case InStr(LCase(SQL), "select")
If InStr(LCase(SQL), "where") <> 0 Then
Dim s As String
s = LCase(SQL)
s = Mid(s, InStr(s, "where"), Len(s) - 1 - InStr(s, "where"))
s = Replace(s, "where", "")
If InStr(s, "order by") <> 0 Then
s = Left(s, InStr(s, "order by") - 1)
End If
Dim i As Integer
Dim patt As String = "\s{1}((={1})|([like]{4}))\s{1}'{1}((.*?){1,})'{1}(((\)){1})|(\s{1}))"
Dim objRegExp As System.Text.RegularExpressions.Regex
Dim Matches As System.Text.RegularExpressions.MatchCollection
Dim Match As System.Text.RegularExpressions.Match
Matches = objRegExp.Matches(s, patt, System.Text.RegularExpressions.RegexOptions.IgnoreCase)
If Matches.Count > 0 Then
For Each Match In Matches
Dim T As String
T = Match.Value
T = Trim(T)
If Right(T, 1) = ")" Then
T = Left(T, Len(T) - 1)
End If
If InStr(T, "like") <> 0 Then
T = Mid(T, 7, Len(T) - 7)
Else
T = Mid(T, 4, Len(T) - 4)
End If
T = Trim(T)
If InStr(T, "''") = 0 Then
SQL = Replace(SQL, T, Replace(T, "'", "''"))
End If
Next
End If
End If
Case InStr(LCase(SQL), "update")
Dim s As String
s = LCase(SQL)
s = StrReverse(s)
s = StrReverse(Left(s, InStr(s, "tes") - 1))
s = Left(s, InStr(s, "where") - 1)
s = Trim(s)
Dim Sarr As Array = Split(s, ",")
Dim i As Integer
For i = 0 To UBound(Sarr)
Dim s2 As String = Sarr.GetValue(i).tostring
s2 = Trim(s2)
s2 = StrReverse(s2)
s2 = Trim(StrReverse(Left(s2, InStr(s2, "=") - 1)))
s2 = Mid(s2, 2, Len(s2) - 2)
If InStr(s2, "''") = 0 Then
SQL = Replace(SQL, s2, Replace(s2, "'", "''"))
End If
Next
End Select
Return SQL
End Function
Funkar säkert sålänge ingen vill skriva någon text med ordet update eller where. Lite som simpsonsavsnittet när Homer skulle bli journalist men hans skrivmaskin saknade bokstäverna e och a.
FixSQLInjection("update tbl set question = 'Where do you live?' ")
Dessutom förtår jag inte varför du vill validera en komplett sql-sats? Varför inte bara validera informationen från användaren? För inte låter man användaren definera sql-satser själv? (Även ifall en av mina gamla arbetsplatser skickade sql-koden i querystring) Alltså:
a = sqlProof(request.form("a")
b = sqlProof(request.form("b")
sql = "update x set c = '"& a &"', d = '"& b &"'"
Fuktionen är till för att man skall slippa att köra "sql.replace("'", "''")" på indata från användaren. Det finns nog många som jag som glömmer att göra det och då kan det vara bra att ha en sådan här funktion.
R/
cyprys skrev:
Funkar säkert sålänge ingen vill skriva någon text med ordet update eller where. Lite som simpsonsavsnittet när Homer skulle bli journalist men hans skrivmaskin saknade bokstäverna e och a.
FixSQLInjection("update tbl set question = 'Where do you live?' ")
Tja, defina scheman på hur de olika sql-satserna kan se ut och dela upp satsen i mer atoma delar där man bara kör de nödvändiga semantiska kontrollerna. Alltså inget efter where i invärden. Men det kanske finns enklare metoder men hur som helst är det inget jag skulle rekommendera. Sålänge du inte gör en total analys av samtliga möjliga sql-satser kommer funktionen vara 'halvfärdig', även inkl. sub-querys m.h.a. rekursion m.m.
Dessutom förlorar 'kodaren' kontroll över sin kod eftersom man ofta vill ha specifika krav på indata. (t.ex. ålder > 0 osv) Då blir det ett slags dubbelt arbete om man först ska validera indata och sen köra denna funktion fast komplett.
Vilken härlig funktion, men framför allt vilket onödigt jobb (y)
Det finns ett bättre sätt. Och det är att använda sql parametrar. sql parametrar är nog det enda sättet att skydda sig mot SQL injections eftersom det är nästan omöjligt att spärra mot alla hundratals olika T-SQL commandon som finns.
Mina vänner. Det finns ett mycket bättre sätt. Och det är att använda sql parametrar. sql parametrar är nog det enda sättet att skydda sig mot SQL injections eftersom det är nästan omöjligt att spärra mot alla hundratals olika T-SQL commandon som finns.
Jo det är möjligt men om man redan har byggt ett system så är det jobbigt att bygga om...
Jag tänkte att vi på wf kunde slå våra kloka hjärnor ihop och bygga en sådan här funktion :)
Det är ju inte direkt så att du ska plocka bort alla t-sql-sqlkommandour strängar utan du ska förhindra att strängar blir manupulerade så de tolkas som annat än det är. Har du väl gjort det finns det inte någon direkt möjlighet för att köra ett t-sql-kommando
Det är ju inte direkt så att du ska plocka bort alla t-sql-sqlkommandour strängar utan du ska förhindra att strängar blir manupulerade så de tolkas som annat än det är. Har du väl gjort det finns det inte någon direkt möjlighet för att köra ett t-sql-kommando
För att ta ett exempel:
lägger jag till i input variablarna något av förljande: (pseudokod som jag räknar upp ur mitt huvud)
Så kan jag göra rätt saftiga skador på din databas. Så om jag skickar med lite T-SQL i en input variabel, hur ska du kunna skilja på den skadliga T-SQL och den icke skadliga?. Då får du impementera nån slags artificiell intelligens som checkar T-SQL innan den ska exekveras, kanske nåt neuralt nätverk? :bire.
Skämt åsido. Ska du skydda dig mot SQL injections är det SQL parametrar du ska använda.
Som jag har förstått det så exekveras inte t-sql kommandona om man inte fipplar med ' och andra avgränsare utan läses då endast som ren-tex som ska in i databasen, så skyddar man och ser till att strängen är intakt borde inte det göra skada även om ;SHUTDOWN [ WITH NOWAIT ] skickas in
Som jag har förstått det så exekveras inte t-sql kommandona om man inte fipplar med ' och andra avgränsare utan läses då endast som ren-tex som ska in i databasen, så skyddar man och ser till att strängen är intakt borde inte det göra skada även om ;SHUTDOWN [ WITH NOWAIT ] skickas in
Nej det är fel.
Ponera att din T-SQL sträng ser ut såhär:
SQL="UPDATE customer SET customername='" + varcustomername + "' WHERE customerID=" + varcustomerID;
Om jag nu skriver in i input variabeln varcustomername: test; DROP DATABASE model; UPDATE customer SET customername='test
kommer det du skickar in i SQL Servern bli: UPDATE customer SET customername='test; DROP DATABASE model; UPDATE customer SET customername='test' WHERE customerID=2
Detta är helt legal T-SQL och kommer förstöra din databas rätt fett. Vilket inte var vad du ville eller?. Eftersom du inte använder Sql parametrar kommer man kunna skriva in vilken skadlig T-SQL som helst eftersom alltihopa betraktas som en enda lång T-SQL sträng vid exekveringen.
natas
så du menar att SQL = "SELECT * FROM t WHERE c='" & "DROP DATABASE model;" & "'"
som blir SQL = "SELECT * FROM t WHERE c='DROP DATABASE model;' "
kommer då "DROP DATABASE model;" att köras?
du måste skriva ' före DROP för att den skall köras och -- efteråt så det inte blir fel...
Därför kör man med replace(inputdata, "'", "''") så då kommer den bahandla det som en sträng istället...
du måste skriva ' före DROP för att den skall köras och -- efteråt så det inte blir fel...<
Om du har tex denna när customersID är numerisk:
SQL="DELETE FROM customers WHERE customersID=" + Request.QueryString["varcustomersID"];
Kan man lägga till det mesta efteråt.
Men jag förstår inte varför du inte använder Sql parametrar, att försöka skriva sin egen check för att ta bort otillåtna tecken är som att uppfinna ett trähjul när du har ett riktigt gummihjul med Sql parametrar. Varför?
natas, jag använder alltid sqlparameters, men svara gärna på min fråga, är inte riktigt hundra på hur den kan få in tsql-kommandon om min sträng ser ut så här
SQL="DELETE FROM customers WHERE customersID="+ Request.QueryString["varcustomersID"]+";
kommer det du skickar in i SQL Servern bli:
UPDATE customer SET customername='test; DROP DATABASE model; UPDATE customer SET customername='test' WHERE customerID=2
Detta är helt legal T-SQL och kommer förstöra din databas rätt fett.
Om vi skall vara petiga så kommer inte mycket hända eftersom det första SQL statmentet inte är valid, då enkelfnuttarna är ursynk. Om vi däremot ändra så den ser ut så här, så kommer det bli värre.
UPDATE customer SET customername='test**'**; DROP DATABASE model; UPDATE customer SET customername='test' WHERE customerID=2
DELETE FROM customers WHERE customersID=1 DROP DATABASE model
Likadant här. Vi måste in med ;
DELETE FROM customers WHERE customersID=1**;** DROP DATABASE model
Men jag håller fullständigt med dig, att INTE använda sig av parametriserade frågor eller en SP är som att tiga om problem.
Sedan finns det en annan aspekt också och det kräver att det userId som man använder när man loggar in på databasen faktiskt har rättigheter till köra alla dessa komando på respektive databas, vilket kanske inte är att rekomendera. om man använder sig av SQL Server så "best practise" att man accessar databasen via SP's som har restriktiva accessrättigheter, vilket betyder att den person som används i connectionstringen bara har rättigheter på SP'n och därmed är man garanterad mot allt vad SQL Injections heter, dels via rättigheter och dels via SP...
- M
260 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2