webForumDet fria alternativet

Spamskydd med verifieringsnyckel

57 svar · 6 929 visningar · startad av MickeA.com

MickeA.comMedlem sedan feb. 20034 441 inlägg
#1

Tjena
Har på senare tid haft jätteproblem med spambottar på min hemsida, så idag gjorde jag ett skydde mot dessa.
Jag vill nu visa denna lösning för er och få lite feedback på hur den kan göras bättre.

Jag har använt en funktion som jag hittade här på wF för att slumpa fram stängar som är 10 tecken långa.

Dessa stängar skriver jag in på en bild som skapas av AspJpeg (www.persits.com).
När formuläret visas så sparas denna slumpade kod i ett hiddenfält och en session med samma värde skapas.

Användaren får fylla i koden som står på bilden i ett fält och vid postning jämförs koden i hiddenfältet, mot den man matat in i rutan.
Samtidigt jämförs den inmatade koden men den kod som sparas i en session på sidan innan.

Här är lite kod:

[i]verify.asp[/i]
<%
' // FUNKTION FÖR ATT SKAPA EN SLUMPMÄSSIG KOD:
Function getChar(ByVal iNoChars)
	Dim sChars, strStr, i
	Randomize(Timer())
	sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	sChars = sChars & "abcdefghijklmnopqrstuvwxyz"
	sChars = sChars & "0123456789"
	For i = 1 to iNoChars
		strStr = strStr & Mid(sChars, Rnd * Len(sChars) + 1, 1)
	Next
	getChar = strStr
End Function

' // SKAPA EN KOD SOM ÄR 10 TECKEN LÅNG:
theCode = getChar(10)
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="sv" lang="sv">
<head>
	<title>Asp Bildverifiering</title>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<meta http-equiv="Content-Language" content="sv" />
	<meta http-equiv="expires" content="Mon, 1 Jul 2002 00:00:00 GMT" />
	<meta http-equiv="pragma" content="no-cache" />
	<meta http-equiv="imagetoolbar" content="no" />
	
<!--
######################################
#    BILDVERIFIERING MED ASPJPEG     #
#  SKRIVEN AV MICKE ANDERSSON 2006   #
#       [url]http://www.mickea.com[/url]        #
######################################
//-->
</head>
<body>
<img src="createKey.asp?theKey=<%=theCode%>" alt="" /><br /><br />
<form action="" method="post">
<input type="hidden" name="theCode1" value="<%=theCode%>" />
<input type="text" name="theCode2" value="" />
<input type="button" value="Kontrollera" onclick="if(this.form.theCode1.value==this.form.theCode2.value){ alert('Rätt!\n');}else{alert('Fel!\n');}" />
</body>
</html>

Och själv filen som skapar bilder binärt:

[i]createKey.asp[/i]
<%
' // TA EMOT SLUMPAD KOD FRÅN FORMULÄRSIDAN SOM EN QUERYSTRING:
theCode = Trim(Request.Querystring("theKey"))

' // SKAPA ETT OBJEKT AV ASPJPEG:
Set Jpeg = Server.CreateObject("Persits.Jpeg")

' // SKAPA EN NY BILD, BREDD, HÖJD, BAKGRUNDSFÄRG:
Jpeg.New 195, 30, &HFFFFFF

' // RITA EN BORDER RUNT BILDEN:
Jpeg.Canvas.Pen.Color = &H000080 ' Blue
Jpeg.Canvas.Brush.Solid = False ' to avoid solid bar
Jpeg.Canvas.DrawBar 0, 0, Jpeg.Width, Jpeg.Height

' // FORMATERA TYPSNITT; FÄRG:
Jpeg.Canvas.Font.Color = &H000000
Jpeg.Canvas.Font.Family = "Terminal"
Jpeg.Canvas.Font.Bold = True
Jpeg.Canvas.Font.Size = 24
Jpeg.Canvas.Font.Quality = 4
Jpeg.Canvas.Font.BkMode = "Opaque"

' // SKRIVA DEN SLUMPADE KODEN I BILDEN:
Jpeg.Canvas.PrintText 5, 5, theCode

' // SKICKA BILDEN TILL WEBBLÄSAREN BINÄRT:
Jpeg.SendBinary
%>

Så, är det här en bra lösning?
Har suttit och funderat på olika lösningar, men det här ser snyggt ut, det är inte allt för jobbigt för besökaren och jag tror att jag kommer få bort en hel del spam från min sida.
Det finns ett demo här på min sajt:
http://www.mickea.com/?mP=fileArea&fType=1

Och filerna i dess helhet finns att ladda hem här:
http://www.mickea.com/?mP=fileArea&fId=14

Alla tips, förslag osv. tas emot så jag kan göra det här så säkert som möjligt.

Tack på förhand!

K@llenMedlem sedan mars 20032 667 inlägg
#2

Ungefär den lösning som brukar användas. Men är inte 10 tecken lite overkill?

MickeA.comMedlem sedan feb. 20034 441 inlägg
#3

K@llen skrev:

Ungefär den lösning som brukar användas. Men är inte 10 tecken lite overkill?

Jo det kanske är så, kanke mer lagom mer ex. vis 6 tecken?
Funderade lite fram och tillbaks och från början (som ni ser i min kod ovan) så blandade jag versaler, gemener och siffror i koden.
Men tyckte den blev för jobbigt, så ändrade till att bara använda stora bokstäver samt siffror.
Sedan valde jag ett enkelt typsnitt (terminal) som gör ett snéstreck genom nollor (0) för att man ska kunna skilja på 0 och O på ett lätt sätt.

Fler synpunkter emottas gärna!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#4

Nä, kollade precis på sidan.
Sedan klockan ett när jag la ut det här på sidan, så har fem nya spam kommit, alla från olika ipadresser...

Vad ska man behöva ta sig till för att få bukt med det här..?
Att förbjuda länkar är inte instressant, vill att mina besökare ska kunna posta URL'er i sina inlägg.

Vad göra?

emissionMedlem sedan dec. 19996 721 inlägg
#5

Frånsett det faktum att flera spamrobotar börjar bli bra på att analysera bilder och skriva i texten själv, så finns ett generalfel i koden, och det är att du lägger med själva nyckelkoden i HTML-koden, på två ställen till och med.

Lägg koden i en sessionsvariabel i stället för i formuläret.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#6

emission skrev:

Frånsett det faktum att flera spamrobotar börjar bli bra på att analysera bilder och skriva i texten själv, så finns ett generalfel i koden, och det är att du lägger med själva nyckelkoden i HTML-koden, på två ställen till och med.

Lägg koden i en sessionsvariabel i stället för i formuläret.

Aha, okej.
Kan det funkar bättre om jag krypterar koden som skapas på nått sätt, så att den inte går att utläsa i klartext?

Ska testa lite...

MickeA.comMedlem sedan feb. 20034 441 inlägg
#7

Nu har jag gjort om lite i koden.
Ingen nyckel syns direkt i htmlkoden, en session skapas endast och jämförs med det inmatade fältet.
Koden i sessionen är MD5-krypterad och kan inte läsas i klartext någonstans.

Kod som slumpas fram skickas inte i någon querystring, utan skapas direkt i den fil som genererar bilden.

Har lagt upp det skarpt på min hemsida nu så ska se om jag fått nå mer spam ikväll, men nu tror jag att jag börjar närma mig.

De nya filerna kommer finnas om 5 minuter för hemladdning via min sajt, om någon är instresserad, då på samma adress som jag angav i ett par inlägg uppåt.

emissionMedlem sedan dec. 19996 721 inlägg
#8

Om du lägger endast lägger koden i sessionen så behöver du inte kryptera den.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#9

emission skrev:

Om du lägger endast lägger koden i sessionen så behöver du inte kryptera den.

Nä, det är sant, men gjorde så iaf. ;)
Skulle man kunna lösa det här på nått sätt utan att skriva in en kod i en bild?
Har funderat lite fram och tillbaks, men inte kommit på nått sätt utan bild där man inte behöver presentera koden i klartext.

Förslag?

MickeA.comMedlem sedan feb. 20034 441 inlägg
#10

Härligt!
Den senaste versionen jag gjorde funkar kanonbra.
Har spanat lite i besökloggen de senaste dagarna och adressen varifån spammen tidigare kommit ifrån blir fler, men det finns inte längre några lyckade postningar på sidan.

Verkar alltså funka enormt bra!

TonyboyMedlem sedan jan. 200554 inlägg
#11

Grymt bra initiativ Micke!!! Har själv under en längre tid efterlyst om mer diskussion kring detta ämne som många är drabbade. Många tvingas tom stänga ner gästböcker etc pga dessa spamrobotar och all spam som dom sprider. Tack igen!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#12

Tonyboy skrev:

Grymt bra initiativ Micke!!! Har själv under en längre tid efterlyst om mer diskussion kring detta ämne som många är drabbade. Många tvingas tom stänga ner gästböcker etc pga dessa spamrobotar och all spam som dom sprider. Tack igen!

Kul att någon har nytta för grejjorna!
Det enda som är lite halvtrist för många är ju just att AspJpeg krävs, jag vet inte hur många webbhotell som stöder det.
Nu går det ju alldeles utmärkt att använda den komponent man vill, men det kräver ju viss modifikation.

Hur som helst verkar det här funka kanon, har inte råkat ut för ett enda spam till sedan jag lade upp den här funktionen, trots att besöken från dessa bottar fortsätter som "vanligt".

SiluettMedlem sedan apr. 200122 inlägg
#13

Jättebra ide! jag skulle gärna vilja låna detta till min sida, problemet är att jag inte får det att fungera, det går bra att skriva inlägg oavsett vad för felaktigt lösenord man skriver. Någon som har något tips? lite kod:

<H1>MEDDELANDE</H1>
<form method="post" action="message.asp?do=add" name="message" onSubmit="return Gb()">
<b>Namn:</b><br><input type="text" name="namn" size="20" class="form">
<b>E-mail:</b> <br><input type="text" name="mail" size="20" class="form">
<b>Hemsida:</b> <br><input type="text" name="url" size="20" class="form">
<b>Meddelande:</b><br><textarea name="msg" cols="16" rows="3" class="form"></textarea>

\<img src="createKey.asp" alt="" /\>\<br /\>\<br /\>
Ange lösenordet ovan för att kunna posta ditt inlägg
\<input type="text" name="keyCode" value="" /\>
\<%End If%\>

<input type="submit" value="Posta inlägg" class="form" onclick="if(this.form.keyCode.value!=''){this.form.submit();}" /></form>

emissionMedlem sedan dec. 19996 721 inlägg
#14

Det kanske inte har med problemet att göra, men eftersom din "Posta"-knapp submittar formuläret via javascript så bör den inte vara en "submit", utan en "button".

MickeA.comMedlem sedan feb. 20034 441 inlägg
#15

Siluett skrev:

Jättebra ide! jag skulle gärna vilja låna detta till min sida, problemet är att jag inte får det att fungera, det går bra att skriva inlägg oavsett vad för felaktigt lösenord man skriver. Någon som har något tips?

Som jag nämnde ovan så är koden i inlägget högst upp inte intressant längre.
Har du laddar hem den senaste versionen från min sida?
Det låter som om du inte gör någon jämförelse mellan sessionen värde och det man matat in i textrutan.
I filen createKey.asp skapas en session som krypteras.

Session("keyCode") = MD5(theCode)
Session.TimeOut = 3

När du sedan postar formuläret, på den sida där variablerna läggs in i databasen, måste du köra:

If Session("keyCode") = MD5(Trim(Request.Form("keyCode"))) Then
      'KÖR DATABASFRÅGAN
Else
      'SKRIV UT MEDDELANDE OM ATT FEL KOD ANGAVS
End If

Visa gärna hela ditt script, inkl. sidan där du sparar uppgifterna i databasen, så blir det lite lättare att hjälpa dig ;)

/r PS: Glöm inte att använda [ kod] [/ kod] taggarna när du postar kod, så blir det lättare att se vad du menar. DS.

SiluettMedlem sedan apr. 200122 inlägg
#16

Ok :-) Ja Här är min kod för att lägga in meddelanden då:

<%Set Conn = Server.CreateObject("ADODB.Connection") 
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db

If Request.Querystring("do")= "" Then%>

<H1>MEDDELANDE</H1>
<form method="post" action="message.asp?do=add" name="message"  onSubmit="return Gb()">
<b>Namn:</b><br><input type="text" name="namn" size="20" class="form">
<b>E-mail:</b> <br><input type="text" name="mail" size="20" class="form">
<b>Hemsida:</b> <br><input type="text" name="url" size="20" class="form">
<b>Meddelande:</b><br><textarea name="msg" cols="16" rows="3" class="form"></textarea>

	<%
	If Trim(Request.Querystring("do")) = "add" Then
	keyCode = Trim(Request.Form("keyCode"))
	If MD5(keyCode) <> Session("keyCode") Then
		Response.Write("<h1>Du har angett en felaktig verifieringsnyckel...</h1>" & VbCrLf)
	Else
		Response.Write("<h1>Du angav rätt verifieringsnyckel!</h1>" & VbCrLf)
	End If
	Session("keyCode") = ""
	Session.Abandon
	Else
	%>

	<img src="createKey.asp" alt="" /><br /><br />
	Ange lösenordet ovan för att kunna posta ditt inlägg
	<input type="text" name="keyCode" value="" />
	<%End If%>
	
<input type="submit" value="Posta inlägg" class="form" onclick="if(this.form.keyCode.value!=''){this.form.submit();}" /></form>

<%Set Recset = Server.CreateObject("ADODB.Recordset")

Sidan = Request.QueryString("next")
If Sidan = "" then 
    sida = 1 
Else 
    sida = Sidan 
End If 

With RecSet
    .CursorLocation = 3
    .CacheSize = InlaggPerSida
End With

SQL = "Select * From message Order By datum desc"
RecSet.Open SQL, Conn

If RecSet.EOF Then%>
<i>Inga meddelanden.</i>

<%Else%>

<%With RecSet
     .MoveFirst 
     .PageSize = InlaggPerSida
     .AbsolutePage = sida
End With

Sidor =  RecSet.PageCount
If Sidor > 1 Then%>

<%End If
X = 0
Do While Not RecSet.EOF And X < RecSet.PageSize%>
<b><%=Recset("namn")%></b> <%If RecSet("url") <> "" Then%><a href="<%=RecSet("url")%>" target="_blank"><img src="bilder/homepg.gif" border="0" alt="<%=RecSet("url")%>"></a> <%End If%> <%If RecSet("mail") <> "" Then%><a href="mailto:<%=RecSet("mail")%>"><img src="bilder/email.gif" border="0" alt="<%=RecSet("mail")%>"></a><%End If%>
<br><%=FormatDateTime(RecSet("datum"),2)%>
<br><%=Link(RecSet("msg"))%>
<br><img src="bilder/line.gif" width="150" border="0" height="1">

<%X = X+ 1 
Recset.MoveNext
Loop
If Sidor > 1 Then%>

     <%For Sid = 1 To Sidor
         If (Int(Sid)) = (Int(sida)) Then%><b><%=FixDigits(Sid,2)%></b><%Else%> <a href="message.asp?next=<%=Sid%>"><%=FixDigits(Sid,2)%></a> <%End If
     Next%>

<%End If
Recset.Close
Set Recset = Nothing
End If

If Request.QueryString("do") = "add" Then

   Namn       = Request.Form("namn")
   Mail          = Request.Form("mail")
   Msg	        = Fixa(Request.Form("msg"))
   Ip   	  = Request.Servervariables("REMOTE_ADDR")
   Url   	  = Request.Form("url")
   If Url <> "" Then
     If Left(Url,7) = "http://" Then
       Url = Url
     Else
       Url = "http://" & Url
     End If
   End If

   Conn.Execute("Insert Into message(namn, mail, url, msg,ip) Values('"& namn &"','"& mail &"','"& url &"','"& msg &"','"& Ip &"')")
   Response.Redirect "aktuellt.asp"
End If

End If
Conn.Close
Set Conn=Nothing%>

Det som händer nu om man postar ett inläg, oavsett lösenord rätt eller fel, är att det blir en helvit sida...

och min sida finns här http://www.pernillas.nu/dog/aktuellt.asp (om det var det du menade?)

MickeA.comMedlem sedan feb. 20034 441 inlägg
#17

Till att börja med, din kod är väldigt rörig ;)
Du har If Request.Querystring("do") = "add" två gånger.
Bygg gärna upp dina sida med ElseIf istället för med flera "egna" ifsatser, så är chansen större att det blir rätt.
Jag ska reda ut din kod lite grann, återkommer snart!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#18

Sådär, nu har jag en liten bättre koll.
Det ställe där du postar (sparar) dina formulärsdata, ligger innanför Request.Querystring("do") = "" vilket gör att den delen av sidan aldrig kan anropas, efter som samma variabel ("do") måste innehålla "add".

Förstår du?

Bygg istället upp din sida såhär:

If Request.Querystring("do") = "add" Then
     ' SPARA FORMULÄRSDATA OCH GÖR JÄMFÖRELSE
Else
     ' VISA FORMULÄR OCH ALLA DINA INLÄGG
End If

Som du har det nu har du väldigt många separata ifsatser, plus att det (som jag nämner ovanför) finns If Request.Querystring("do") = "add" två gånger, en i början och en längst ner.
I nuläget körs det som finns i ifsatsen längst ner, så din jämförelse du gör, högst upp körs aldrig, eftersom den biten bara körs om "do" är tom, vilket den inte kan vara för att formuläret skall postas på det ställe du vill.

Förstår du vad jag menar?

MickeA.comMedlem sedan feb. 20034 441 inlägg
#19

Nu har jag skrivit om din kod, så det ska funka.
Kan ju inte provköra den, men det borde inte vara något problem.
Om du jämför din kod med min, så är det ingen större skillnad.

Det jag gjort är att reda ut alla dina ifsatser och bytt plats på saker, så att:
- Om Request.Querystring("do") = "add" så postas formuläret, koderna jämförs och sqlfrågan körs.
- Formuläret och alla inlägg visas om Request.Querystring("do") INTE är "add", alltså "do" = "".

<%
Set Conn = Server.CreateObject("ADODB.Connection") 
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db

If Request.Querystring("do")= "add" Then%
' POSTA FORMULÄRET, JÄMFÖR DEN HEMLIGA KODEN OCH SPARA:
	keyCode = Trim(Request.Form("keyCode"))
	If MD5(keyCode) <> Session("keyCode") Then
		Response.Write("<h1>Du har angett en felaktig verifieringsnyckel...</h1>" & VbCrLf)
	Else
		Response.Write("<h1>Du angav rätt verifieringsnyckel!</h1>" & VbCrLf)
	End If
	Session("keyCode") = ""
	Session.Abandon

	Namn       = Request.Form("namn")
	Mail          = Request.Form("mail")
	Msg	        = Fixa(Request.Form("msg"))
	Ip   	  = Request.Servervariables("REMOTE_ADDR")
	Url   	  = Request.Form("url")
	If Url <> "" Then
		If Left(Url,7) = "http://" Then
			Url = Url
		Else
			Url = "http://" & Url
		End If
	End If
   Conn.Execute("Insert Into message(namn, mail, url, msg,ip) Values('"& namn &"','"& mail &"','"& url &"','"& msg &"','"& Ip &"')")
   Response.Redirect "aktuellt.asp"

Else
%>
<!-- VISA FORMULÄR //-->
<H1>MEDDELANDE</H1>
<form method="post" action="message.asp?do=add" name="message"  onSubmit="return Gb()">
<b>Namn:</b><br><input type="text" name="namn" size="20" class="form">
<b>E-mail:</b> <br><input type="text" name="mail" size="20" class="form">
<b>Hemsida:</b> <br><input type="text" name="url" size="20" class="form">
<b>Meddelande:</b><br><textarea name="msg" cols="16" rows="3" class="form"></textarea>
<img src="createKey.asp" alt="" /><br /><br />
Ange lösenordet ovan för att kunna posta ditt inlägg
<input type="text" name="keyCode" value="" />
<input type="submit" value="Posta inlägg" class="form" onclick="if(this.form.keyCode.value!=''){this.form.submit();}" /></form>
<%

' VISA RESTEN AV INLÄGGEN:
	Set Recset = Server.CreateObject("ADODB.Recordset")

	Sidan = Request.QueryString("next")
	If Sidan = "" then 
		sida = 1 
	Else 
		sida = Sidan 
	End If 

	With RecSet
		.CursorLocation = 3
		.CacheSize = InlaggPerSida
	End With

	SQL = "Select * From message Order By datum desc"
	RecSet.Open SQL, Conn

	If RecSet.EOF Then
%>
	<i>Inga meddelanden.</i>

<%
	Else
%>

<%
		With RecSet
			 .MoveFirst 
			 .PageSize = InlaggPerSida
			 .AbsolutePage = sida
		End With

		Sidor =  RecSet.PageCount
		If Sidor > 1 Then
%>

<%
		End If
		X = 0
		Do While Not RecSet.EOF And X < RecSet.PageSize%>
		<b><%=Recset("namn")%></b> <%If RecSet("url") <> "" Then%><a href="<%=RecSet("url")%>" target="_blank"><img src="bilder/homepg.gif" border="0" alt="<%=RecSet("url")%>"></a> <%End If%> <%If RecSet("mail") <> "" Then%><a href="mailto:<%=RecSet("mail")%>"><img src="bilder/email.gif" border="0" alt="<%=RecSet("mail")%>"></a><%End If%>
		<br><%=FormatDateTime(RecSet("datum"),2)%>
		<br><%=Link(RecSet("msg"))%>
		<br><img src="bilder/line.gif" width="150" border="0" height="1">

<%
		X = X + 1 
		Recset.MoveNext
		Loop
		If Sidor > 1 Then
%>

<%
			 For Sid = 1 To Sidor
				 If (Int(Sid)) = (Int(sida)) Then%><b><%=FixDigits(Sid,2)%></b><%Else%> <a href="message.asp?next=<%=Sid%>"><%=FixDigits(Sid,2)%></a> <%End If
			 Next
%>

<%
		End If
		Recset.Close
		Set Recset = Nothing
	End If
End If
Conn.Close
Set Conn=Nothing
%>

Prova nu och återkom!

SiluettMedlem sedan apr. 200122 inlägg
#20

Oj! Stort tack!! ja, det är lätt att det blir rörigt när man skriver om och ändrar om :-)

hm...
'type mismatch' på If MD5(keyCode) <> Session("keyCode") Then

jaha??

144 ms totalt · 3 externa anrop · v20260731065814-full.86db40fa
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
141 ms — hämta tråd, inlägg och bilagor (db)