webForumDet fria alternativet

Login, Sessions, SQL injections, Säkerhet, Databas

4 svar · 545 visningar · startad av Emil RT

Emil RTMedlem sedan feb. 2004200 inlägg
#1

Ska försöka sammanfatta det jag tror jag kan efter att ha vigt ett bra stund till genomsökning på forumet. Är väldigt tacksam för kommentarer!

Mitt mål är att skapa en inloggningssida som är säker! Så säker den KAN bli förutom att använda certifikat vill säga.

  1. Först och främst - databasen.
    Den läggs ovanför wwwroot på servern.
    server/wwwroot/index.asp
    server/db/databas.mdb
    Detta förhindrar från att användare kan ändra/ladda hem/förstöra databasen. Om webbhotellet har spärrat mappen vill säga. Detta innebär alltså att databasen inte behöver lösenordsskyddas.

  2. Ändå döper jag databasen till bcbcbvvcdsadsadasd.mdb och lösenordsskyddar den. En fattigmanskryptering mao:)

  3. Inkluderade filer ska inte heta .inc utan .asp för att förhindra nedladdning av dem och därigenom läsning av kod.

  4. Databas skyddas mot SQL-injections
    http://www.sitepoint.com/article/sql-injection-attacks-safe

I mitt fall använder jag Access och vill få bort '
Passar dessutom på att rensa bort lite annat obehag som rekomenderades i artiklen ovan.

Ta bort fnutt mm.

function safeSQL(strText)
    strText = replace(strText,"'","''")
    dim badChars 
    dim newChars 
    badChars = array("select", "drop", ";", "--", "insert",  "delete", "xp_") 
    newChars = strText 
    for i = 0 to uBound(badChars) 
        newChars = replace(newChars, badChars(i), "") 
    next 
    strText=newChars
    safeSQL=strText
end function
user = safeSQL(Request.Form ("uname"))
pass = safeSQL(Request.Form ("pword"))

SQL-fråga

sql = "select * FROM users WHERE " & _
          	    "User = '" & user & "' and " & _
          	    "Pass = '" & pass & "' "

Begränsar dessuom inputfälten för att ytterliga försvåra strul.

<input name="uname" type="text" maxlength="15">
  1. Ett övrigt tillägg till SQL-injections som jag läst om men inte ser ut att behöva applicera här är att titta om ID och dylikt är numeriskt med "isNumeric()" eller konvertera direkt t ex CLng(Request.QueryString("ID")).

  2. Slutligen är det dags för själva loginchecken och kollen att man är inloggad. Iom att det är ASP som gäller så förutsätter jag att SESSIONS är säkrast och bäst. Läste någonstans att det slöar ner men hellre det än intrång (i databasen).

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<!--#include file="global_scripts/oDB.asp"-->
	<% If Request("action")="" Then 
    	Session.abandon()
	%>
<!DOCTYPE HTML Public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Login</title>
</head>
<body>

	<form method="post" action="login.asp?action=login">
  		USER: <input name="uname" type="text" maxlength="15">
  		<br>
  		PASS: <input name="pword" type="password" maxlength="15">
  		<br>
	  <br>
        <input type="submit" name="Submit" value="Submit">
	</form>

	<%
	Else
   		dim user, pass, nextpage
   		
		function safeSQL(strText)
			strText = replace(strText,"'","''")
			
			dim badChars 
			dim newChars 

			badChars = array("select", "drop", ";", "--", "insert",  "delete", "xp_") 
			newChars = strText 

			for i = 0 to uBound(badChars) 
				newChars = replace(newChars, badChars(i), "") 
			next 
			strText=newChars
			safeSQL=strText
		end function
		
		
		user = safeSQL(Request.Form ("uname"))
		pass = safeSQL(Request.Form ("pword"))

		Set Rs=Server.CreateObject("ADODB.Recordset")
		
		sql = "select * FROM users WHERE " & _
          	"User = '" & user & "' and " & _
          	"Pass = '" & pass & "' "
	
		Rs.Open sql, DataConn
		If NOT Rs.EOF Then
   			Session("userId")=RS(0)
    		nextPage="default.asp"
    	Else
    		nextPage="login.asp"
    	End If

		Response.Redirect(nextPage)
		
	End If
	%>

</body>
</html>
<!--#include file="global_scripts/cDB.asp"-->

Och den skyddade sidan default.asp ....

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<%
'cacha inte sidan
Response.Expires=0
Response.ExpiresAbsolute = Now() -2
Response.AddHeader "pragma", "no-cache"
Response.AddHeader "cache-control", "private"
Response.CacheControl = "no-cache"
'om sessionen inte finns åker man till inloggningssidan
If Session("userId")="" Then
   Response.Redirect("login.asp")
Else
%>
<!DOCTYPE HTML Public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Skyddad sida</title>
</head>
<body>
    Denna sida &auml;r skyddad ...<br>
    <a href="login.asp">Logga ut</a>
</body>
</html>
<%End If%>

I början av loginsidan har jag Session.abandon() för att tömma sessionen om man kommer dit genom att logga ut t ex. På de skyddade sidorna kollar jag sessionen samt säger till att sidan inte ska cachas.

Så vad tror vi? Som sagt väldigt tacksamt för svar:)

Laddar även upp min testmiljö för lek och testning:)

/Emil

spangoMedlem sedan juni 20008 205 inlägg
#2

Emil RT skrev:

  1. Databas skyddas mot SQL-injections
    http://www.sitepoint.com/article/sql-injection-attacks-safe

I mitt fall använder jag Access och vill få bort '
Passar dessutom på att rensa bort lite annat obehag som rekomenderades i artiklen ovan.

Tycker att förslagen på sista sidan i den där artikeln var rätt dåliga. Att skydda sig från injektioner genom att ta bort "farliga" tecken eller fraser är värdelöst. Använd parametriserade frågor (sök här i forumet) så kan man skriva in vad som helst utan att kunna härja runt i din databas.

Då slipper du även quotingfunktioner som safeSQL. För det första är de bökiga, en extra grej att använda överallt, de kräver att du verkligen kommer ihåg ALLA kombinationer som kan ställa till problem, och inte ens då är de nödvändigtvis säkra. I PHP kunde man en gång i tiden lura sig runt quotingfunktioner genom att använda kluriga kombinationer av teckenuppsättningar. Med lite otur dyker det upp något likadant till ASP. Kanske inte så sannolikt, men icke desto mindre är quotingfunktioner en extra potentiell felkälla som kan undvikas med parametriserade frågor.

Sen, om man vill ha mer lätthanterad kod och därmed färre säkerhetsrisker, ska man använda sig av ett Riktigt Webbramverk, som ASP.NET eller J2EE, inte en scriptlösning som ASP.

Emil RTMedlem sedan feb. 2004200 inlägg
#3

Ska kolla upp parametriserade frågor! Tackar ...

Det är ASP som är the shit nu i detta fallet. Kan dock tänka mig att det finns bättre ramverk.

Men om parametriserade frågor implementeras och man bortser från att ASP inte är 100 - vad är statusen på ovanstående? Är det säkert eller ej?

/E

emissionMedlem sedan dec. 19996 721 inlägg
#4

1. Bra!
2. Ja, det skadar inte
3. Utan tvekan! Ett måste!
4. Håller med spango. Om man måste skydda sig genom att ta bort specifika ord så är man helt fel ute. Parametriserade frågor (ADODB.Command) är det som gäller om man vill ha totalt injection-skydd. Dessutom ger det vissa prestandafördelar och det är, inte minst, roligare att använda, jämfört med konkateneringshysterin som man kan hamna i annars.
5. IsNumeric ska man inte lita på, utan den bör endast användas i valideringssammanhang. Typomvandling är däremot att rekommendera.
6a. Det är riktigt att sessioner är lite prestandakrävande, men det blir inte hållbart att bygga ett inloggningssystem utan dem (man kan överleva med endast egna cookies, men då får man bygga en hel del runt ikring, som antagligen blir mer prestandakrävande)
6b. Funktionsdeklaration ska ligga utanför flödet, dvs. inte inne i en "else"

I övrigt såg det helt ok ut.

Spango har helt rätt när han skriver "Sen, om man vill ha mer lätthanterad kod och därmed färre säkerhetsrisker, ska man använda sig av ett Riktigt Webbramverk, som ASP.NET eller J2EE, inte en scriptlösning som ASP."

Det primära där är inte ASP:s tillkortakommanden, utan just att "lätthanterad kod [ger] färre säkerhetsrisker". Sträva efter att göra ditt system enkelt och strukturerat, så kan du bygga fullgod säkerhet även i ASP.

Emil RTMedlem sedan feb. 2004200 inlägg
#5

Bra feedback!

Varför jag la en funtion i elsesatsen kan bara min sovande hjärna svara på. I "verkligheten" hade jag nog inkluderat en fil ist. Jag har med den här ändå trots att ni ni sagt nej till att byta ut ord. Mest för att sammanfatta vad som är sagt.

Har tittat på ...
http://www.swesecure.com/?ID=dc6ea60a-12ae-4e7e-9e9c-59489ccafa90&IID=d628e96e-f8fd-44ed-9537-4061c817e9b1
... för att bli klok på parameteriserade frågor. Finns inte så mycket exempel här i forumet. Det hela bygger på att man byter ut värdena mot frågetecken och sedan byter ut dem mot riktiga värden.

En fråga dock. I vanliga fall skapar jag ett rs (recorset) med

Set Rs=Server.CreateObject("ADODB.Recordset")

I detta exemplet skapar man ett command ist och sedan ett rs av det. Vad är relationen?

Och så koden ...

<%@LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<!--#include file="global_scripts/oDB.asp"-->
	<%
		function safeSQL(strText)
			strText = replace(strText,"'","''")
		
			dim badChars 
			dim newChars 

			badChars = array("select", "drop", ";", "--", "insert",  "delete", "xp_") 
			newChars = strText 

			for i = 0 to uBound(badChars) 
				newChars = replace(newChars, badChars(i), "") 
			next 
			strText=newChars
			safeSQL=strText
		end function
	%>
	
	<% 
		If Request("action")="" Then 
    		Session.abandon()
	%>
<!DOCTYPE HTML Public "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Login</title>
</head>
<body>

	<form method="post" action="login.asp?action=login">
  		USER: <input name="uname" type="text" maxlength="15">
  		<br>
  		PASS: <input name="pword" type="password" maxlength="15">
  		<br>
	  <br>
        <input type="submit" name="Submit" value="Submit">
	</form>

	<%
	Else
   		dim Rs,cmd, user, pass, nextpage
   		
		user = safeSQL(Request.Form ("uname"))
		pass = safeSQL(Request.Form ("pword"))
		
		'orginal
		'Set Rs=Server.CreateObject("ADODB.Recordset")
		'sql = "select * FROM users WHERE " & _
          	'"User = '" & user & "' and " & _
          	'"Pass = '" & pass & "' "
		'Rs.Open sql, DataConn
		
		'param
		Set cmd = server.createobject("ADODB.command")
		cmd.activeConnection = DataConn
		sql = "SELECT * FROM users WHERE (User=? AND Pass=?)"
		cmd.CommandText = sql
		
		Set Rs=cmd.Execute(, array(user, pass))
		
		If NOT Rs.EOF Then
   			Session("userId")=RS(0)
    		nextPage="default.asp"
    	Else
    		nextPage="login.asp"
    	End If

		Rs.Close 
		Set Rs=nothing
		Response.Redirect(nextPage)
		
	End If
	%>

</body>
</html>
<!--#include file="global_scripts/cDB.asp"-->
250 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
117 ms — hämta statistik (db)
130 ms — hämta tråd, inlägg och bilagor (db)