Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Satunnaisluvun luominen vain kerran

Sivun loppuun

Resiina [25.08.2007 13:48:36]

#

Tässä on tällainen floodibottiestokoodikuva tai miksikä sitä sanotaankaan.
Kun vieraskirjan (guestbook.php) lomake lähetetään, niin satunnaisluku, mikä jo kerran on luotu, luodaan uudestaan, jolloin käyttäjän kirjoittama luku ei kelpaa varmistuskoodiksi.
Miten satunnaisluku luotaisiin vain kerran?

// guestbook.php

<?php
$code = rand(100, 999);
print "<form ...
<img src=\"image.php?n=$code\">
...
</form>";
$ucode = $_POST['code'];
if ($ucode == $code)
{
  // lähetetään viesti vieraskirjaan
}
?>
// image.php

<?php
header("Content-type: image/png");

$num = $_GET['n'];

$image = imagecreate(75, 20);

$bg = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 255);

imagerectangle($image, 0, 0, 74, 19, $black);
imagestring($image, 5, 25, 2, $num, $blue);
imageline($image, 0, 10, 74, 10, $black);

imagepng($image);
imagedestroy($image);
?>

T.M. [25.08.2007 13:59:30]

#

Ite tallennan noi koodit tiedostoon joka sivunlatauksella, ja sieltä sitten tarkistan löytyykö sitä käyttäjän antamaa koodia tietyllä aikavälillä, eli ei hyväksy esim tunti sitten luotuja koodeja.

Resiina [25.08.2007 14:18:38]

#

Siis tarkoititko, että kaikkien käyttäjien IP:t ja koodit kirjoitettaisiin samaan tiedostoon, ja sieltä sitten vertailtaisiin niitä?

Tässä vielä linkki sivulle, jossa tuo vieraskirja on.

ajv [25.08.2007 14:28:04]

#

offtopic: Voi muuten toimiakkin. Meinaan monet spämmibotit osaavat kaivaa tuon tekstin tuosta kuvasta, mutta kuinka moni spämmibotti osaakaan kaivaa sen tekstin siitä kuvan nimen perästä (image.php?n=148) :)

Resiina [25.08.2007 14:31:42]

#

Joo pitää varmaankin jonkinlainen numeroiden vaihto kirjaimiksi pistää tuohon, jos osaan...

ajv [25.08.2007 14:32:40]

#

Mikset vain luo sitä satunnaislukua tuolla image.php:ssä?

Resiina [25.08.2007 14:36:00]

#

Miten saan sen satunnaisluvun sitten guestbook.php:hen?

ajv [25.08.2007 14:41:07]

#

Kuten T.M. sanoi, tallennat koodit tiedostoon ja kun lomake on lähetetty tarkistat tiedoston.

Resiina [25.08.2007 14:44:10]

#

Olen jo kokeillut sellaista, että kirjoitan koodin image.php:ssä tekstitiedostoon, ja se toimiikin aivan oikein, JOS joku toinen käyttäjä ei käytä vieraskirjaa samaan aikaan, sillä silloin koodi tiedostossa vaihtuu.

kayttaja-2791 [25.08.2007 14:45:56]

#

ajv kirjoitti:

[offtopic]
Voi muuten toimiakkin. Meinaan monet spämmibotit osaavat kaivaa tuon tekstin tuosta kuvasta, mutta kuinka moni spämmibotti osaakaan kaivaa sen tekstin siitä kuvan nimen perästä (image.php?n=148) :)
[/offtopic]

Tuota ajatusta voi vielä viedä eteenpäin, eli jos käyttää siinä urlissa vaikka eri kantajärjestelmää, niin ei varmasti mikään spämmiohjelma sitä ala purkamaan... Tai jotain muuta salakirjoitusta käyttää.

ajv [25.08.2007 14:47:00]

#

No älä kirjota sen tiedoston päälle, vaan perään (append, eli a-moodi);) Ja sitten kun luku on käytetty, niin poistat vain sen tietyn numeron sieltä tiedostosta (samalla voit poistaa nuo yli tunnin vanhat).

ajv [25.08.2007 14:48:23]

#

JTS kirjoitti:

Tuota ajatusta voi vielä viedä eteenpäin, eli jos käyttää siinä urlissa vaikka eri kantajärjestelmää, niin ei varmasti mikään spämmiohjelma sitä ala purkamaan... Tai jotain muuta salakirjoitusta käyttää.

Joo, mut jos se spämmibotti osaa kuitenkin lukea sen siitä kuvasta, ni ehkä vähän turhaa... :)

kayttaja-2791 [25.08.2007 14:59:59]

#

Juu, pieni ajatuskatko, tai epäselvyys siitä mitä tässä nyt haettiin oli...

Itse tosin en noin monimutkaista lähtisi virittämään, mutta onhan se captcha teoriatasolla ihan mielenkiintoinen tietty tehdä.

Resiina [25.08.2007 15:04:42]

#

guestbook.php:

<?php
$codes = file("codes.txt");
for ($i = 0; $i < count($codes); $i++)
{
	$codes[$i] = str_replace("\n", "", $codes[$i]);
	if ($codes[$i] == $ucode)
	{
		$post_allowed = true;
		$fileo = fopen('codes.txt', 'w');
		fwrite($fileo, "");
		fclose($fileo);
		$fileo = fopen('codes.txt', 'a');
		for ($ind = 0; $ind < count($codes); $ind++)
		{
			if ($ind != $i)
			{
				fwrite($fileo, "$codes[$ind]\n");
			}
		}
		fclose($fileo);
		break;
	}
}

image.php:

<?php
header("Content-type: image/png");

$num = rand(100, 999);

$image = imagecreate(75, 20);

$bg = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 255);

imagerectangle($image, 0, 0, 74, 19, $black);
imagestring($image, 5, 25, 2, $num, $blue);
imageline($image, 0, 10, 74, 10, $black);

imagepng($image);
imagedestroy($image);

$fileo = fopen('codes.txt', 'a');
fwrite($fileo, "$num\n");
fclose($fileo);

Ei pysty kirjoittamaan vieraskirjaan tämmösellä systeemillä.

E: kappas tuollahan on toi 'w' virhe...
E: koodia muokattu, ei toimi vieläkään

Varmaankin pitäisi tuossa poistaa noista $codes:n alkioista '\n'... vaan eipä auttanu.

Oho alkas toimimaan ku vaihdoin $codes[$i] == ... -> $codes[$i] = ... :-)

Mutta nyt tuonne codes.txt voi floodata mielin määrin vain päivittämällä sivua... :-/ Kuinkas ne turhat koodit sieltä poistetaan?

Antti Laaksonen [25.08.2007 15:25:01]

#

Minusta koodeja ei kannata tallentaa tiedostoon, vaan paljon helpompaa on lisätä lomakkeeseen piilokenttä, johon kirjoitettu koodi välittyy seuraavalle sivulle. Kuvan osoitteessa ja piilokentässä koodi kannattaa salata jotenkin - esim. jos koodin kääntää ympäri ja lisää loppuun satunnaisen luvun, ei sitä mikään automaattinen ohjelma ymmärrä.

Muoks. Tässä vielä pikku esimerkki:

*** skuva.php
<?php

$kuva = imagecreate(100, 100);

$valko = imagecolorallocate($kuva, 255, 255, 255);
$musta = imagecolorallocate($kuva, 0, 0, 0);

$koodi = strrev(substr($_GET['koodi'], 0, -1));
imagerectangle($kuva, 0, 0, 99, 99, $musta);
imagestring($kuva, 4, 20, 20, $koodi, $musta);

header("Content-type: image/png");
imagepng($kuva);

?>
*** ssivu.php
<?php

if ($_POST['koodi'] <> "") {
    $koodi1 = $_POST['koodi'];
    $koodi2 = strrev(substr($_POST['skoodi'], 0, -1));
    if ($koodi1 == $koodi2) {
        die("Oikein meni!");
    } else {
        die("Väärin meni!");
    }
}

$koodi = rand(10000, 99999);
$skoodi = strrev($koodi) . "1";

?>
<form action="ssivu.php" method="post">
<img src="skuva.php?koodi=<?php echo $skoodi; ?>">
<p>Kirjoita kuvassa näkyvä koodi:</p>
<input type="text" name="koodi">
<input type="hidden" name="skoodi" value="<?php echo $skoodi; ?>">
<input type="submit" value="Lähetä">
</form>

Resiina [25.08.2007 15:48:20]

#

Mutta jos satunnaisluku tehdään joka latauksella niin se muuttuu aina, sehän tässä alunperin ongelma oli. Vai ymmärsinkö väärin kenties?

Edit: luetaanpas....

Antti Laaksonen [25.08.2007 15:50:41]

#

Tuolla voi kokeilla äskeistä esimerkkiä:
http://koti.mbnet.fi/pllk/muut/ssivu.php

Kyllä se toimii ihan hyvin, kun aluksi arvotun luvun lähettää lomakkeella.

Resiina [25.08.2007 16:33:36]

#

guestbook.php:

<?php
$code = rand(10000, 99999);
$hcode = strrev($code) . "1";

$nick = $_POST['nick'];
$post = $_POST['post'];
$ucode = strrev(substr($_POST['code'], 0, -1));

if (strlen($post) > 0 && $ucode == $hcode)
{
	if (strlen($nick) < 1)
	{
		$nick = "Unknown";
	}
	$post = str_replace("<", "&lt;", $post);

	// ...

	$fileo = fopen('guestbook.txt', 'a');
	fwrite($fileo, $post);
	fclose($fileo);
}
?>

<img src="image.php?c=<?php echo $hcode; ?>"><br>
<input type="hidden" name="hcode" value="<?php echo $hcode; ?>"><br>
Write the code here:<br>
<textarea name="code" type="text" style="width: 300; height: 20;"></textarea><br><br>

image.php:

<?php

header("Content-type: image/png");

$code = strrev(substr($_GET['c'], 0, -1));

$image = imagecreate(75, 20);

$bg = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 255);

imagerectangle($image, 0, 0, 74, 19, $black);
imagestring($image, 5, 15, 2, $code, $blue);
imageline($image, 0, 10, 74, 10, $blue);

imagepng($image);
imagedestroy($image);

?>

Vieraskirjaan ei voi kirjoittaa, eli ilmeisesti ehto $ucode == $hcode ei toteudu. Missä vika?

E: Vaihdoin
$ucode = $_POST['code'];
->
$ucode = strrev(substr($_POST['code'], 0, -1));
mutta ei toimi.

Antti Laaksonen [25.08.2007 18:29:19]

#

Tulosta muuttujien $code, $hcode ja $ucode arvot ennen vertailua, niin paljastuu, miksi vertailu on tai ei ole tosi. Tällä menetelmällä löytää muutenkin lähes kaikki virheet PHP-ohjelmista. Lomakkeella on kenttä hcode, mutta miksi se jätetään huomiotta lomakkeen käsittelyssä?

Cornix [25.08.2007 19:04:44]

#

Antti Laaksonen kirjoitti:

Minusta koodeja ei kannata tallentaa tiedostoon, vaan paljon helpompaa on lisätä lomakkeeseen piilokenttä, johon kirjoitettu koodi välittyy seuraavalle sivulle. Kuvan osoitteessa ja piilokentässä koodi kannattaa salata jotenkin - esim. jos koodin kääntää ympäri ja lisää loppuun satunnaisen luvun, ei sitä mikään automaattinen ohjelma ymmärrä.

Just totahan captcha-jutuissa vältetään, että kirjotettas sitä edes salattuna sinne sivulle. Tollasen ku voi kuitenki ihminen purkaa ja sitten kirjottaa botin, joka spämmäilee niitä viestejä.

Ite oon käyttäny PHP:n sessioita tallentaan tietoa väliaikasesti. Se tarttee kyllä keksit päälle selaimesta tai sitte PHPSESSID:n kuljettamista osoterivillä, mutta koodaaminen on niin paljo helpompaa ku tekstitiedoston käyttö, että tapa on mun mielestä hyvä. (edit: molemmat session id-numeron siirtotavat PHP hoitaa automaattisesti)

Tässä pieni esimerkki luvun arpomisesta tuon aiemman skriptin pohjalta:

<?php
session_start();

$_SESSION['salasana'] = rand(10000, 99999);
?>

Sitten voidaan tarkistaa siinä lomakkeen käsittelyssä if-lauseella:

<?php
if ($_SESSION['salasana'] == $_POST['tarkistekentta']) { /* Oli oikein */ } else { /* Ei täsmännyt! */ }
?>

edit: Kannattaa tarkistaa myös, että tarkistekenttä on yleensäkin täytetty esimerkiks isset()-funktiolla. En tähän esimerkkiin sitä laittanu ensin, ku idea piti vaan tuoda esille. :)

Antti Laaksonen [25.08.2007 19:39:39]

#

Cornix kirjoitti:

Just totahan captcha-jutuissa vältetään, että kirjotettas sitä edes salattuna sinne sivulle. Tollasen ku voi kuitenki ihminen purkaa ja sitten kirjottaa botin, joka spämmäilee niitä viestejä.

Tämä uhka taitaa olla kuitenkin lähinnä teoreettinen. Tai ainakin minun on vaikea uskoa, että joku ohjelmoisi erillisen järjestelmän suomalaisen yksityishenkilön vieraskirjan sotkemiseen. Jos salaus on vähänkin monimutkaisempi, sen purkaminen on myös niin vaikeaa, että paljon nopeampaa on lähettää haluttu määrä roskaviestejä käsin.

Cornix [25.08.2007 20:47:48]

#

Onkohan muuten sellasia roskapostiskriptejä olemassa, jotka kyselis käyttäjältä ensi jonku kymmenisen kertaa, että "mitä tässä captchassa lukee nyt?" ja sitte päättelis, onko joku hidden-kenttä yhteydessä siihen jollain tietyllä kaavalla? Vois kuvitella, että sellasia vois ollakin.

moptim [25.08.2007 21:31:05]

#

Vois kuvitella että tommosen hidden-kentän käytön voi kiertää helposti. Just tolla Cornixin mainitsemalla tavalla. Jos on riittävän raskas salaus, sen purussa kestää myös vieraskirjaskriptillä.

Grez [25.08.2007 21:37:38]

#

Aika hiton ääliö kooderi silti olisi, jos lähettäisi jotain siihen captchan sisältöön liittyvää tietoa siinä lomakkeen yhteydessä.

Resiina [25.08.2007 22:00:16]

#

Sain tuon nyt sitten lopulta toimimaan vaihtamalla koodin järjestykseen:

Tarkistetaan syötteet
Kirjoitetaan tiedostoon, jos ok
Tehdään satunnaisluku

Eli satunnaisluku tehdään vasta tiedostoon kirjoittamisen jälkeen, jolloin se ei haittaa enää.
Nyt toimii, kiitos kaikille avusta.

PS. Tästähän voisi saada kenties hyvän koodivinkin? Vai lieneekö sellainen jo olemassa...

Cornix [26.08.2007 00:13:49]

#

Mutta kuinkas sitten käy, jos välissä tulee eri selaimelta sivupyyntö? Silloin salasanasi muuttuu tiedostossa, eikä aiemmin sivun ladanneelle näy uusi ennen uutta sivunlatausta. Aiemmin sivun ladannut on myös saattanut kirjoittaa pitkän viestin, jota ei pystykään lähettämään, kun tunnusluku onkin yhtäkkiä väärä.

Grez [26.08.2007 01:06:48]

#

Antti Laaksonen kirjoitti:

Tämä uhka taitaa olla kuitenkin lähinnä teoreettinen. Tai ainakin minun on vaikea uskoa, että joku ohjelmoisi erillisen järjestelmän suomalaisen yksityishenkilön vieraskirjan sotkemiseen.

Minun mielestäni silti se, että kyseessä on yksityishenkilön vieraskirja ei ole mikään järkevä peruste tehdä asioita huonosti, jos ne voidaan tehdä hyvinkin.

Huonosti tekeminen ainoastaan:
- Opettaa huonoille tavoille
- Iskee selkään, jos myöhemmin lainailee koodia aiemmista projekteistaan.

Itse tekisin tuon niin, että sivun yhteydessä tulee ID-koodi ja ko. ID-koodilla viitataan myös kuvaan. ID-koodi on siis juokseva numero eikä se liity mitenkään kuvan sisältämään merkkijonoon. ID:t ja niitä vastaavat merkkijonot sitten säilytetään tietokannassa (tai jos ei mahdollista niin tiedostossa). Lisäksi siinä voi olla tietona, kuinka kauan koodi on voimassa ja mahdollisesti montako kertaa sitä on yritetty. Näiden perusteella voidaan sitten estää liian vanhojen tai liian monta kertaa yritettyjen koodien käyttö sekä siivota vanhoja pois halutuissa puitteissa.

Tosin tässä tapauksessa tuo kuva täytyisi tehdä joka tapauksessa paremmin, nykyisellään älykäs spämmibotti tunnistaa tekstin tuosta aivan ongelmitta.

Resiina [26.08.2007 01:18:26]

#

Cornix kirjoitti:

Mutta kuinkas sitten käy, jos välissä tulee eri selaimelta sivupyyntö? Silloin salasanasi muuttuu tiedostossa, eikä aiemmin sivun ladanneelle näy uusi ennen uutta sivunlatausta. Aiemmin sivun ladannut on myös saattanut kirjoittaa pitkän viestin, jota ei pystykään lähettämään, kun tunnusluku onkin yhtäkkiä väärä.

Kirjoitetaan siis vieraskirjaan, eikä sitä koodia kirjoiteta mihinkään.

Grez [26.08.2007 01:25:47]

#

Sitten jos ei itse jaksa kehittää kunnon captcha tekniikkaa, niin ainahan on mahdollista hyödyntää esim. reCaptchaa http://recaptcha.net/

T.M. [26.08.2007 13:35:54]

#

Grez kirjoitti:

Antti Laaksonen kirjoitti:

Tämä uhka taitaa olla kuitenkin lähinnä teoreettinen. Tai ainakin minun on vaikea uskoa, että joku ohjelmoisi erillisen järjestelmän suomalaisen yksityishenkilön vieraskirjan sotkemiseen.

Minun mielestäni silti se, että kyseessä on yksityishenkilön vieraskirja ei ole mikään järkevä peruste tehdä asioita huonosti, jos ne voidaan tehdä hyvinkin.

Huonosti tekeminen ainoastaan:
- Opettaa huonoille tavoille
- Iskee selkään, jos myöhemmin lainailee koodia aiemmista projekteistaan.

Niinpä. miksi tehdä asioita huonosti kun ne voi tehdä satavarmaksi vain hieman suuremmalla vaivalla? Tuollainen ajatusmalli tosiaan opettaa vain laiskaksi koodaajaksi / bugiviljelijäksi... sitten vaan mikkisoftalle töihin ;)

Antti Laaksonen [26.08.2007 14:19:36]

#

Jos on kysymys pelkästä tiedon lähetyksestä lomakkeen kautta, minusta tuntuu aika huvittavalta rakentaa niinkin yksinkertaiseen asiaan monimutkainen tiedosto-, tietokanta- tai istuntojärjestelmä. Ohjelmistahan ei pidä tehdä täydellisiä vaan riittävän hyviä, ja jos lomakkeen tiedon salaa vaikka kaavalla "muutetaan luku 7-järjestelmään ja otetaan jakojäännös viikonpäivän neliöllä", taitaa olla todennäköisempää saada viisi kertaa peräkkäin loton päävoitto kuin että joku tuon suojauksen murtaa.

Grez [26.08.2007 14:23:28]

#

Imo tuollaisen "muutetaan luku 7-järjestelmään ja otetaan jakojäännös viikonpäivän neliöllä" ja siihen päälle sen kuvan generoiva skripti on ensinnäkin työläämpi toteuttaa kuin vaikkapa tuon recaptchan käyttöönotto. Kuitenkaan tuosta ei ole hirveästi hyötyä, sillä noin yksinkertaisen captchan joku ocr-spämmäysbotti selvittää vaivattomasti.

Ja toisekseen kuvaamasi systeemi on "security through obscurity", jota en ainakaan itse pidä lähtökohtaisesti hyvänä käytäntönä.

Ja ainakin jos itse olisin tekemässä tuota, niin mieluummin tekisin hyvän, käyttäisin 5 minuuttia enemmän aikaa ja oppisin samalla jotain hyödyllistä. En mitenkään voi uskoa että tässä on nyt 5 minuutista kiinni.

Grey [26.08.2007 15:12:10]

#

Ei sitä kannata opetella hyväksi koodaajaksi. Tulee vain elitistikusipääksi, kun alkaa luulla liikoja itsestään ja lopulta pimahtaa täysin..

-Grey-

T.M. [26.08.2007 15:22:34]

#

Kyllä kannattaa. Elitistikusipääthän tätä maailmaa johtavat ;)

Grey [26.08.2007 15:26:05]

#

T.M. kirjoitti:

Kyllä kannattaa. Elitistikusipääthän tätä maailmaa johtavat ;)

Mutta eihän Bush johda mitään. Se on vain kulissi ja sätkynukke O__o

-Grey-

T.M. [26.08.2007 16:01:43]

#

En kyllä puhunut Bushista yhtään mitään o_O

Grez [26.08.2007 16:24:05]

#

Grey kirjoitti:

Ei sitä kannata opetella hyväksi koodaajaksi. Tulee vain elitistikusipääksi, kun alkaa luulla liikoja itsestään

Tuo on sikäli ristiriitaista, että hyvä ohjelmoija tietää, ettei tiedä kaikkea.

arcatan [26.08.2007 19:11:49]

#

Grez kirjoitti:

Sitten jos ei itse jaksa kehittää kunnon captcha tekniikkaa, niin ainahan on mahdollista hyödyntää esim. reCaptchaa http://recaptcha.net/

Kas, tuohan vaikuttaa kätevältä. Kiitos vihjeestä. Olen aiemminkin nähnyt tuon sivun, mutta en ollenkaan muistanut sen olemassaoloa. Eräällä ylläpitämälläni sivulla on shoutbox-tyylinen keskustelu, jonka roskaviestibotit ennen pitkää varmasti löytävät. Minua ei huvitta keksiä pyörää uudelleen, varsinkaan PHP:lla, ja tuo vaikuttaa aika asialliselta valmisratkaisulta.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta