webForumDet fria alternativet

Säkra från sql-injections

ASP

15 svar · 854 visningar · startad av Vinnaren

Medlem sedan sep. 2005833 inlägg
Frågan#1

Hej

Jag är lite nyfiken på om jag kan förbättra säkerheten något på min sida.

1.
Jag har en inloggning med bla denna kod som kollar upp medlemmen.

struserAnvandarnamn		 = SafeSQL(Request.Form ("userAnvandarnamn"))
		struserLosen 			 = SafeSQL(Request.Form ("userLosen"))
		
		
		Set objRS = objConn.Execute("SELECT * FROM anvandare Where userAnvandarnamn = '" & struserAnvandarnamn & "' AND userLosen = '" & struserLosen & "'")

SafeSQL är..:

Function SafeSQL(strText)
strText = replace(strText,"'","''")
strText = Replace(strText,"\","\\")
strText = Replace(strText,"  "," ")
strText = Replace(strText," .",".")

With New RegExp
   .Global = True
   .IgnoreCase = True

   .Pattern = "^(script)$"
   strText = .Replace(strText ,"[script]")

   .Pattern = "^(html)$"
   strText = .Replace(strText ,"[html]")
   
   .Pattern = "^(<)$"
   strText = .Replace(strText ,"[")
   
   .Pattern = "^(>)$"
   strText = .Replace(strText ,"]")

End With
SafeSQL = strText
end function

2.
Sen när jag ska hämta något från databasen så har jag följande kod tex:

Set objRS = objConn.Execute("SELECT * FROM tabell WHERE ID ="&CLng(Request.QueryString("ID")))

tacksam för alla tips som jag kan få till att göra sidan "säkrare" :bire

Medlem sedan dec. 19996 721 inlägg
#2

Genom att använda typomvandling med CLng och en SafeSQL-funktion så är det nästan så säkert som det kan bli. Nästa steg blir att använda parametriserade frågor, mha ADODB.Command, vilket totalt tar bort injection-risken.

Din SafeSQL-funktion gör dock mer än den borde. Utrensning av potentiellt skadlig html- och skriptkod ska definitivt inte göras i en SafeSQL-funktion. Dels för att det inte har med SQL att göra, dels för att dylika rutiner ska köras på data som skickas ut till sidan, men inte på data som skickas in till databasen.

Medlem sedan dec. 20025 483 inlägg
#3

Vad gäller CLng() får du se upp med strängvärden och tal som är för stora.

Medlem sedan sep. 2005833 inlägg
#4

ok, tack, då vet jag det.

men när man ska kontrollera utdata från tabellen räcker det då med denna:


Function makeTags(ByVal text)

		text = Replace(Server.HTMLEncode(text),vbCrlf,"<br>")
		text = Replace(text,"(t)", "&nbsp;&nbsp;&nbsp;&nbsp;")									
		Set regExp = New regexp
		regExp.Global = true
		regExp.IgnoreCase = true
														
		RegExp.Pattern="\(b\)(.*?)\(/b\)"
		text = regExp.Replace(text,"<b>$1</b>")
														
		regexp.pattern = "\(i\)(.*?)\(/i\)"
		text = regexp.replace(text,"<i>$1</i>")
														
		regexp.pattern = "\(u\)(.*?)\(/u\)"
		text = regexp.replace(text,"<u>$1</u>")
												
		regexp.pattern = "\(center\)(.*?)\(/center\)"
		text = regexp.replace(text,"<center>$1</center>")

	
		regExp.Pattern = "(http://|www)([\S]*)"
	   text = regExp.Replace(text,"<a href=""http://$1$2"" target=""_blank"">$1$2</a>")
	
	   regExp.Pattern = "(ftp://)([\S]*)"
	   text = regExp.Replace(text,"<a href=""$1$2"" target=""_blank"">$1$2</a>")
	
	   regExp.Pattern = "([\S]*@[\S]*[.se|.com|.nu|.net|.org])"
	   text = regExp.Replace(text,"<a href=""mailto:$1"" target=""_blank"">$1</a>")
	
	   regExp.Pattern = "([.|,|!|?|:|;|)|\|&]]*)</a> "
	   text = regExp.Replace(text,"</a>$1 ")
	
	   regExp.Pattern = "([.|,|!|?|:|;|)|\|&]]*)"" target=""_blank"">([^<]*)</a>"
	   text = regExp.Replace(text,""">$2</a>")
	
	   text = Replace(Trim(text),vbCrLf, "<br>")
	   text = Replace(Trim(text),"http://http://", "http://")

	Set RegExp = Nothing
	makeTags = text
						
End Function

eller e det något mer som borde vara med?? :stud

Medlem sedan feb. 200112 078 inlägg
#5

Peter S skrev:

Vad gäller CLng() får du se upp med strängvärden och tal som är för stora.

På vilket sätt ska man se upp med detta? Om en sträng dyker upp i en CLng() så ska det ju smälla. Och så vitt jag erfarat så har man väldigt sällan problem med storleken på en Long (-2,147,483,648 till 2,147,483,647). Rena talidentifierare brukar sällan överstiga 2 miljarder..

Medlem sedan juni 20003 076 inlägg
#6

OveRRide skrev:

På vilket sätt ska man se upp med detta?

Om man inte har egendesignade errorsidor så kan det vara bra att passa upp lite.
Om man tänker sig en webshop där man vill se en viss produkt utifrån en querystrings id och detta id inte är ett nummer så kraschar hela sidan.
Om du däremot "safe"ar upp CLng så visas webshopen fortfarande fast utan produkt.
I sånna fall kan man köra en egen CLng-funktion enligt nedan. :)

'formaterar CLng==================================================
Public Function c_lng(str)
	str = Trim(str)
	If Len(str) = 0 Then Exit Function
	
	If isNumeric(str) Then c_lng = Clng(str)
End Function
Medlem sedan feb. 200112 078 inlägg
#7

doggelito skrev:

OveRRide skrev:

På vilket sätt ska man se upp med detta?

Om man inte har egendesignade errorsidor så kan det vara bra att passa upp lite.
Om man tänker sig en webshop där man vill se en viss produkt utifrån en querystrings id och detta id inte är ett nummer så kraschar hela sidan.
Om du däremot "safe"ar upp CLng så visas webshopen fortfarande fast utan produkt.
I sånna fall kan man köra en egen CLng-funktion enligt nedan. :)

'formaterar CLng==================================================
Public Function c_lng(str)
	str = Trim(str)
	If Len(str) = 0 Then Exit Function
	
	If isNumeric(str) Then c_lng = Clng(str)
End Function

Jag ser fortfarnade inte meningen. Det finns två fall då det, enligt mig, kan komma in felaktig data i denna parameter;

1. Det finns en felaktig länk
2. Någon har roligt (?) med dina querystrings (läs: sql injection)

Detta anser jag ska generera fel, såvida det inte *förväntas* och *måste* hanteras. Jag ser ingen som helst anledning till detta, eftersom det är just ett talvärde, och inte en sträng.

Dessutom, om du bara hoppar ur funktionen vid en felkonvertering, vad blir värdet då? Om du inte ytterligare hanterar avsaknaden av t.ex. returnerad data (EOF på recordset'et, som exempel), så kommer det ju smälla ändå.

Medlem sedan juni 20003 076 inlägg
#8

Tja, det kanske har mer att göra med sin programeringsbakgrund att göra.
Jag försöker i alla fall alltid att bygga system som inte ska gå att krascha med flit.

Precis som man kontrollerar t.ex. att en epostadress i Request.Form är en korrekt adress så kollar jag så att ett idnummer Request.Querystring är ett nummer och inte tar för givet att det är det.

Men det är ju jag det! :)

Medlem sedan dec. 19996 721 inlägg
#9

Det är klart att man kan hantera indatafel på ett snyggare sätt, men när det gäller att skydda sig mot injections så är det inte primärt. Såvida det inte är en känslig (och felbyggd) transaktionsprocess så kan man knappast krascha en ASP-applikation genom att trigga ett typomvandlingsfel. Den c_lng-funktion som du beskriver hjälper ju dessutom inte alls, eftersom den kan returnera nullvärden. Möjligen kan man önska sig en funktion i stil med

function TryParseDouble(byval stringVal,byref doubleVal) //returnerar bool
Medlem sedan juni 20003 076 inlägg
#10

Kanske blev lite sidospår av detta.
Min funktion har inte nått med sqlinjektioner att göra, det har jag heller aldrig påstått.
Utan mitt svar var en utveckling av Peter S svar på att man "bör" uppmärksamma hanteringen av CLng(), inget annat.

Och detta för att slippa komma till: Internal server error-sida (om man inte har egendesignade errorsidor)

Det kan mycke väl vara så att man har ett cms-system eller liknande där man länkar interna sidor hårdkodade och då kan det slinka in en bokstav istället för en siffra i bara farten.

Medlem sedan sep. 2005833 inlägg
#11

ok, tack. då ska jag försöka göra en felsida så man slipper se "standard" sidan vid fel.

Då är jag lite nyfiken på om det jag nämde i inlägg 4, om det räcker med den "kontroll" jag har där när data skrivs ut eller om det är något som saknas/är fel??

Medlem sedan feb. 200112 078 inlägg
#12

doggelito skrev:

Tja, det kanske har mer att göra med sin programeringsbakgrund att göra.
Jag försöker i alla fall alltid att bygga system som inte ska gå att krascha med flit.

Mig veterligen så crashar inte ett system på grund av ett typkonverteringsfel.

doggelito skrev:

Precis som man kontrollerar t.ex. att en epostadress i Request.Form är en korrekt adress så kollar jag så att ett idnummer Request.Querystring är ett nummer och inte tar för givet att det är det.

Men det är ju jag det! :)

Om datat är och skall vara inmatat av en användare, som t.ex. en e-postadress, så skall den givetvis valideras, eftersom användare är korkade. Data som används som rena identifierare däremot anser jag inte att man behöver hantera så hårt; de ska generera fel.

Man vill ha fel i de här lägena för att kunna följa upp med felsökning bättre och för att överhuvudtaget kunna logga dem. Och det gör man inte genom att gå runt dem på det viset. En 500-sida som loggar felet till databas och skriver ut en snygg text är en lösning.

Men man tar aldrig bort felet. Det är min åsikt. Funktionen kastar ett fel av en anledning, inte för att man ska bygga lösningar för att få den att inte göra det.

Medlem sedan juni 20003 076 inlägg
#13

OveRRide skrev:

Mig veterligen så crashar inte ett system på grund av ett typkonverteringsfel.

Det beror på hur man definerar krasch! :)
Följande kod genererar: type mismatch

If CLng("felfel") = CLng(12345) Then
...						
End If

Vilket i mina ögon är en krasch.

Lite kul med sånna här trådar när man skriver nått och får en massa mothugg! :)
För då tar man sig tid och funderar varför man gör på ett visst sätt och andra gör på ett annat.
I detta fall kan jag berätta att jag kört på c_lng av gammal vana sen den tiden jag inte visste vad felhantering var. Det har bara rullat på så att säga.

c_lng ska ha tack för lång och trogen tjänst men jag måste hålla med om att en korrekt felhantering är att föredra! :)

Medlem sedan sep. 2005833 inlägg
#14

ok, då har jag följande fråga kvar. Håller då på met ett litet forum så jag undrar då om det räcker med följande kod som kontrollerar utdatan från databasen??

Vinnaren skrev:

ok, tack, då vet jag det.

men när man ska kontrollera utdata från tabellen räcker det då med denna:


Function makeTags(ByVal text)

		text = Replace(Server.HTMLEncode(text),vbCrlf,"<br>")
		text = Replace(text,"(t)", "&nbsp;&nbsp;&nbsp;&nbsp;")									
		Set regExp = New regexp
		regExp.Global = true
		regExp.IgnoreCase = true
														
		RegExp.Pattern="\(b\)(.*?)\(/b\)"
		text = regExp.Replace(text,"<b>$1</b>")
														
		regexp.pattern = "\(i\)(.*?)\(/i\)"
		text = regexp.replace(text,"<i>$1</i>")
														
		regexp.pattern = "\(u\)(.*?)\(/u\)"
		text = regexp.replace(text,"<u>$1</u>")
												
		regexp.pattern = "\(center\)(.*?)\(/center\)"
		text = regexp.replace(text,"<center>$1</center>")

	
		regExp.Pattern = "(http://|www)([\S]*)"
	   text = regExp.Replace(text,"<a href=""http://$1$2"" target=""_blank"">$1$2</a>")
	
	   regExp.Pattern = "(ftp://)([\S]*)"
	   text = regExp.Replace(text,"<a href=""$1$2"" target=""_blank"">$1$2</a>")
	
	   regExp.Pattern = "([\S]*@[\S]*[.se|.com|.nu|.net|.org])"
	   text = regExp.Replace(text,"<a href=""mailto:$1"" target=""_blank"">$1</a>")
	
	   regExp.Pattern = "([.|,|!|?|:|;|)|\|&]]*)</a> "
	   text = regExp.Replace(text,"</a>$1 ")
	
	   regExp.Pattern = "([.|,|!|?|:|;|)|\|&]]*)"" target=""_blank"">([^<]*)</a>"
	   text = regExp.Replace(text,""">$2</a>")
	
	   text = Replace(Trim(text),vbCrLf, "<br>")
	   text = Replace(Trim(text),"http://http://", "http://")


	Set RegExp = Nothing
	makeTags = text
						
End Function

eller e det något mer som borde vara med?? :stud

Medlem sedan dec. 19996 721 inlägg
#15

Det ser bra ut. Ur säkerhetssynpunkt har du löst allt med HTMLEncode. Resten är en ren utseendefråga.

Medlem sedan sep. 2005833 inlägg
#16

ok, tack, då vet jag det. Då e det bara att köra på :bire

297 ms totalt · 4 externa anrop · v20260731065814-full.e96017d9
146 ms — deklarationer (db)
0 ms — hämta statistik (cache)
147 ms — hämta tråd, inlägg och bilagor (db)
146 ms — ändringar (db)