webForumDet fria alternativet

Funktion för SQLInjections

.NET

21 svar · 961 visningar · startad av Glitter

Medlem sedan juli 2003465 inlägg
Frågan#1

Hej

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
Medlem sedan dec. 20003 563 inlägg
#2

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 &"'"

Dessutom borde väl

sql.replace("'", "''")

räcka istort sett för input av strängar.

Medlem sedan juli 2003465 inlägg
#3

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?' ")

varför skulle inte det funka på min funktion?

Medlem sedan dec. 19996 522 inlägg
#4

Använd dig av sqlparameters så skyddar du dig automatiskt mot sql-injections

Medlem sedan dec. 20003 563 inlägg
#5

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.

/R

varför skulle inte det funka på min funktion?

Och du har testkört antar jag?

Medlem sedan juli 200568 inlägg
#6

jesus christ :birp

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.

Titta på denna länk:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000002.asp

Medlem sedan juli 2003465 inlägg
#7

Jag gjorde det nu och det funkade inte :r

Medlem sedan juli 2003465 inlägg
#8

natas skrev:

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 :)

Medlem sedan dec. 19996 522 inlägg
#9

natas, vad du e slö på morgonen ;)

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

Medlem sedan dec. 20003 563 inlägg
#10

Jo det är möjligt men om man redan har byggt ett system så är det jobbigt att bygga om...

Det är nog inte lika jobbigt som att göra denna funktion 'funktionell'. ;)

Tips är att använda sqlparameters som tidigare nämnt men om du vägrar ;) så validera i alla fall indatat separat.

Medlem sedan maj 200010 687 inlägg
#11

Oh, jikes!
Den funktionen passar bra in på https://www.thedailywtf.com.

Medlem sedan juli 200568 inlägg
#12

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)

;DROP TABLE customer
;DROP DATABASE model,tempdb,master
;SHUTDOWN [ WITH NOWAIT ]
;EXEC master.dbo.xp_cmdshell 'FORMAT C:'

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.

Medlem sedan dec. 19996 522 inlägg
#13

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

Medlem sedan juli 200568 inlägg
#14

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.

Medlem sedan dec. 19996 522 inlägg
#15

Om du ersätter ' med '' hur tolkar den det då

Medlem sedan juli 2003465 inlägg
#16

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...

Medlem sedan juli 200568 inlägg
#17

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?

Medlem sedan dec. 19996 522 inlägg
#18

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"]+";

om jag ersätter alla ' i variablarna med ''

Medlem sedan juli 200568 inlägg
#19

Innehåller Request.QueryString["varcustomerID"] detta:

1 DROP DATABASE model

Så kommer denna:

SQL="DELETE FROM customers WHERE customersID=" + Request.QueryString["varcustomersID"];

Bli:

DELETE FROM customers WHERE customersID=1 DROP DATABASE model

När du exekverar den till SQL Servern eftersom vid numeriska värden (customersID) inte ska ha några fnuttar.

Medlem sedan maj 20012 812 inlägg
#20

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
122 ms — deklarationer (db)
0 ms — hämta statistik (cache)
135 ms — hämta tråd, inlägg och bilagor (db)
121 ms — ändringar (db)