15. díl - Kniha návštěv - Obrana proti komentářovému spamu

PHP Databáze pro začátečníky Kniha návštěv - Obrana proti komentářovému spamu

(pokračování tohohle textu)

Cílem spammera je rozšířit po internetu co nejvíc odkazů na určité stránky. Vyhledávače si pak myslí, že když na ně vede tolik odkazů z tolika míst, jsou asi fakt dobré, a tak je ve výsledcích zobrazují na přednějších místech.

Většina spammerů to samozřejmě nedělá ručně, ale napíší si na to robota - program, který automaticky prochází internet, hledá slibně vypadající formuláře a zkouší do nich psát. Co jsem tak vypozoroval, spamboti se na našich stránkách chovají zhruba takhle:

  1. Nejdřív se musí zorientovat a najít návštěvní knihu. Orientaci jim velice usnadňují odkazy s texty jako "Guestbook", "Discussion board", "Forum" a podobně. První obrannou taktikou tedy je pojmenovat odkazy nějak jinak - například česky, tomu roboti obvykle nerozumí. Když už potřebujete angličtinu, docela pomáhá, když nahradíte některá písmena ASCII kódy (třeba e místo e) - lidé to přečtou bez problémů, ale pro robota je to úplně jiný řetězec.
  2. Nejhloupější roboti hledání vzdají, ale ostatní dříve nebo později formulář knihy najdou. Nejdřív se podívají, jestli vypadá jako návštěvní kniha. Má aspoň jedno velké textové pole (textarea)? Má odesílací tlačítko, na kterém je v ideálním případě napsáno něco jako "Submit", "Post", "Save" nebo "Send"? Jsou tam ještě nějaká další textová políčka, nejlépe s předvyplněnými hodnotami jako "@", "http://" a tak? Jestli to vypadá slibně, robot do formuláře nasype svoje naprogramované bláboly a odešle je. V té chvíli musí zasáhnout naše druhá a nejdůležitější obranná linie, která rozezná spam od smysluplného příspěvku a zahodí ho. Metody rozpoznávání spamu si podrobněji probereme za chvilku.
  3. Po chvilce si robot stránku znovu načte a podívá se, jak jeho první pokus dopadl. Jestli tam svůj výplod najde, zajásá a začne knihu stejným nebo podobným textem bombardovat, dokud ji úplně nezamoří. Pokud ho ale nenajde, usoudí, že to buď návštěvní kniha není nebo že je nějak moc dobře zabezpečená a odtáhne s nepořízenou (proto se třeba moc nespamuje přes mailovací formuláře). Jestli jsme robota napoprvé neprokoukli a něco už nám do knihy napsal, můžeme ho teď aspoň odlákat tím, že nové příspěvky zobrazíme až po nějakém čase (třeba po hodině nebo po ručním schválení) nebo na jiné stránce. Otázka je, jak moc to pomůže proti spambotům a jestli to spíš neodradí návštěvníky.
  4. Stránky, kde se spamování daří, si roboti určitě dobře zapamatují a budou se tam rádi vracet.

Jak odhalit robota?

I druhou obrannou linii můžeme rozškatulkovat do několika vrstev. V první se snažíme roboty nachytat: zkoumáme, jakým způsobem odeslali formulář nebo kde v něm udělali nějakou botu. Sem patří různé kontrolní otázky, maskované ovládací prvky a podobně. Druhá vrstva zkoumá samotný text vzkazu a snaží se uhádnout, jestli je to spam nebo ne. To ovšem vyžaduje určitý stupeň umělé inteligence a rozsáhlou databázi vzorků, což přesahuje jak úroveň tohoto seriálu, tak úroveň mých znalostí :-). Třetí vrstva jsou různé závěrečné nouzové pojistky (jako třeba omezení počtu příspěvků), které zabrání totálnímu zahlcení knihy v případě, kdyby nějaký chytřejší robot prošel až sem.

Několik různých technik přechytračení robotů si teď probereme podrobněji.

Neviditelné prvky formuláře

Roboti vidí stránku jako HTML zdroják a je jim celkem jedno, jak vypadá v prohlížeči. Nejspíš je ani nenapadne zkoumat všechny přidružené definice CSS, jestli náhodou někde něco nemá vlastnost "display:none". To znamená, že na roboty můžeme nastražit past: pokud něco napíšou do neviditelného textového políčka nebo kliknou na neviditelné tlačítko, máme je - člověk to udělat nemůže.

<html>
<head>
<style type="text/css">
.viditelna {display:block}
.neviditelna {display:none}
</style>
</head>
<body>
<form method="post">
<input type="text" name="jmeno" class="viditelna">
<input type="text" name="past1" value="http://" class="neviditelna">
<textarea name="vzkaz" class="viditelna"></textarea>
<input type="submit" name="past2" value="Submit" class="neviditelna">
<input type="submit" name="odeslani" value="Uložit" class="viditelna">
</form>
...
<?php
if ( isset($_POST['past1']) and ($_POST['past1']<>'http://')
     or isset($_POST['past2']) )
   ...je to robot...
 else
   ...je to člověk...
?>

(Vyhodnocení dat jsem pro přehlednost dal až za hlavičku HTML a formulář, v praxi by bylo zřejmě úplně na začátku, aby se v případě potřeby dala použít funkce header.)

Výhoda téhle taktiky je jasná: neotravuje návštěvníky, protože si jí vůbec nevšimnou. Navíc je velice účinná, obzvláště když alternativních odesílacích tlačítek vytvoříte víc a jen jedno bude správné, případně pokud je ještě navíc náhodně střídáte. Nevýhody? Pokud se sem spammer podívá ručně, prokoukne to hned, svého robota upraví a má vystaráno. Někteří roboti se možná v CSS vyznají a stylu display:none si všimnou. Také nevím, jak by to fungovalo v čistě textových prohlížečích s hlasovým výstupem pro slepce (v nejhorším tam můžeme dát popisky jako "sem nic nepište a na tohle neklikejte, nebo vám to smažu").

Matení Javascriptem

Tak, jako se dá pomocí CSS text skrýt, dá se Javascriptem napsat nebo různě měnit. Se správnou interpretací JS mají občas problémy i některé starší prohlížeče, natožpak roboti. Takže pokud si například formulář zobrazíme pomocí document.write() nebo si vhodným způsobem pohrajeme s událostmi onclick, onsubmit a onchange, zamotají se v tom.

Výhody jsou stejné jako prve: neviditelost pro lidi a účinné odpálkování robotů. Drobná nevýhoda: musíme spoléhat na to, že návštěvníci mají Javascript zapnutý a že jim v prohlížeči funguje tak, jak má. Dešifrování může být obtížné i pro živého spammera, ale jakmile ho prokoukne, napíše si parazitní formulář (tj. kopii našeho formuláře na svém počítači) a už se to s námi poveze.

Kontrola formátu zadaných dat

Tohle už trochu hraničí s inteligentními spamfiltry. Můžeme využít toho, že někteří boti píší dlouhé traktáty tam, kde je nečekáme (do políček pro jména, adresy a tak) nebo umisťují do textu spoustu odkazů (a href=...). Když se nám to nezdá, můžeme příspěvek zahodit. Délku textového řetězce zjistíme pomocí funkce strlen:

if (strlen($_POST['jmeno'])>50)
   ...podezřelé!...
 else
   ...asi v pořádku...

Výhoda: další nenápadná vrstva. Nevýhody: malá účinnost (roboti už většinou tak blbí nejsou) a možnost nechtěného smazání příspěvku od človka (nevěřili byste, jaké hrůzy si v návštěvních knihách vyměňují třeba programátoři).

Kontrola přes session nebo cookie

Tohle nemám ověřené, berte to spíš jako brainstorming. Skript, který zobrazuje formulář knihy, by mohl zároveň do session nebo cookie vložit nějakou proměnnou a při vyhodnocování odeslaných dat zkontrolovat její přítomnost. Nevím, jestli to má vůbec nějaký smysl, ale teoreticky by to aspoň mělo ztížit použití parazitních formulářů.

Turingův test neboli Captcha

Jde o různé kontrolní otázky, opisování pokrouceného textu z obrázků a podobné věci, které by člověk teoreticky měl zvládnout levou zadní, ale roboti by si na nich měli vylámat zuby. Účinnost je zpravidla poměrně slušná, ale hodně záleží na tom, jaký test zvolíme a jak je který robot vybavený. Zásadní nevýhoda je, že testy otravují především lidi a občas jim dělají větší potíže než robotům (nečitelné obrázky apod.). Další mínus je omezená použitelnost pro slepce a textové prohlížeče.

Různých kontrolních testů existuje nepřeberné množství, tady uvedu jenom pár příkladů, se kterými jsem se dosud setkal:

  • Opisování náhodných textů z obrázku. V současnosti jedna z nejrozšířenějších metod. Výhodou je, že stačí připravit algoritmus a potom už to běží samo. Podrobný návod tu právě vychází.
  • Několik zatrhávacích políček, kterými se hodnotí pravdivost výroků jako třeba "jsem člověk", "přišel jsem sem spamovat", "umím číst" a podobně. Kontrolní věty je potřeba předem připravit a čas od času obměňovat, ale zase je výhoda, že jde o ryze textový a dobře čitelný systém.
  • Otázka, na kterou je potřeba odpovědět slovy. Nevýhoda je (kromě nutnosti předem vymyslet otázky) možná nejednoznačnost odpovědi. Třeba na otázku "V čem plavou ryby?" existuje spousta možných odpovědí: ve vodě, v rybníce, v moři, v akvárku atd., plus hromada jinak skloňovaných tvarů, s diakritikou nebo bez.
  • Přepis foneticky zapsaného čísla (např. "stopjetašedesát") do číselného tvaru (165). Chce to předem si připravit čísla (kdyby šla vygenerovat náhodně, nebylo by luštění pro roboty takový problém), ale jinak je to relativně praktická a pohodlná metoda.
  • Několik odesílacích tlačítek a opodál poznámka typu "příspěvek uložíte kliknutím na tlačítko 2", "...kliknutím na tlačítko s nejdelším textem", "...kliknutím na tlačítko úplně nalevo" a podobně. Tady si musíte předem připravit jak texty, tak tlačítka. Ale jinak je to celkem výhodná metoda, protože člověk nemusí zbytečně klikat ani psát nic navíc, jenom se rozhodne, kam ten jeden závěrečný klik umístí.
  • Něco podobného, jenom máme místo odesílacích tlačítek (input type="submit") obrázek (input type="image") a je potřeba kliknout do něj na určité místo (třeba "příspěvek uložíte kliknutím na žirafu"). Souřadnice se předají spolu s ostatními daty formuláře jako proměnné $_POST['x'] a $_POST['y'], počátek 0,0 je v levém horním rohu obrázku. Výhody stejné jako minule, nevýhodou je nečitelnost pro slepce a větší náročnost na místo (potřebujeme spoustu předpřipravených obrázků).
  • Spočítání jednoduché matematické úlohy, třeba 1+3=__, 19-4=__ a podobně. Čísla i operátory se dají generovat náhodně, takže odpadá nutnost něco si předem připravovat. Ovšem naučit robota počítat je triviální věc a jakmile se sem jednou podívá živý spammer, máme po ptákách.
  • Ověření přes mail. Návštěvník do formuláře vyplní svoji mailovou adresu, na tu mu pošleme nějaký odkaz nebo heslo, se kterým něco udělá a až tím dojde k potvrzení odeslaných dat. Velice bezpečné, ale jinak naprosto extrémní pruda použitelná jedině při jednorázových úkonech (třeba registracích), ne pro každodenní psaní do diskusí.

Ale počkat... náhodně vybraný obrázek nebo otázka je hezká věc, ale jak náš skript při vyhodnocování odpovědi pozná, kterou otázku předtím vybral?

První a nejtriviálnější možnost je otázku nějak označit přímo ve formuláři, třeba skrytým prvkem (input type="hidden") s nějakým kódem otázky. Vyhodnocovací algoritmus to potom má jednoduché: patří k tomuhle kódu tahle odpověď? Ano/ne, hotovo. Nevýhoda je v tom, že jakmile se živý spammer mrkne do zdrojáku, vykopíruje si kód otázky do parazitního formuláře, přihodí svoji odpověď a rozjede to ve velkém.

Lepší je kód otázky nějak zamaskovat. Buď tím, že se pošle jinudy než přes formulář (třeba přes session nebo cookie), nebo že se zahashuje, třeba funkcemi md5(), crypt() nebo hash(). Ideálně třeba v kombinaci s aktuálním datem - nikoho nebude bavit každý den ručně krmit robota novým kódem. Nejlepší bude ukázat si to na příkladu. Dejme tomu, že máme otázky a odpovědi uložené v polích $otazky a $odpovedi s indexy od 1 do 100.

echo '<form method="post">';
$cislootazky=rand(1,100); //náhodný výběr otázky
echo $otazky[$cislootazky];
echo '<input type="text" name="odpoved">';
echo '<input type="hidden" name="kontrolnihash" value="'.md5($odpovedi[$cislootazky].date('Ymd')).'">';
echo '<input type="submit" value="Odeslat"></form>';

A teď vyhodnocení:

if (md5($_POST['odpoved'].date('Ymd'))==$_POST['kontrolnihash'])
  ...v pořádku...
 else
  ...špatná odpověď...

Živý spammer sice ze zdrojáku formuláře zjistí, jaký hash odpovídá dnešnímu datu a téhle odpovědi, ale samotné datum ani odpověď z něj nevykouká.

Jo, a máme tu pár nových funkcí: md5 vytvoří z daného řetězce hash (32znakový text z písmen '0'..'f'), rand(a,b) dává náhodné celé číslo z rozsahu a..b a date dává aktuální datum zformátované do daného tvaru (viz manuál). Kdyby nám šlo o bezpečnost (např. šifrování hesel), je lepší místo md5 použít crypt.

To by k captchám zatím mohlo stačit, teď si ještě probereme posledních pár taktik spamové války:

Omezení kadence příspěvků

Tohle už patří do kategorie "poslední záchrana, když všechny předchozí metody selžou". Jde o omezení počtu příspěvků, které se dají odeslat v určitém časovém intervalu (třeba během jednoho dne) z jednoho počítače. Prakticky jediná použitelná identifikace počítačů jsou v tomto případě IP adresy, protože na cookies se nám roboti nejspíš zvysoka vy-víte-co. Počítání přístupů a ukládání IP adres už jsme si nacvičili v předchozích dílech o počítadlech a anketách, takže by to pro vás neměl být problém. Pokud zjistíte překročení maximálního dovoleného počtu, přestanete příspěvky z téhle adresy ukládat a případně rovnou schováte i formulář. Ale počítejte s tím, že se takhle ubráníte jedině amatérům, co spamují ručně z domova. Jakmile je někdo schovaný za proxy serverem, který mu IP každou chvíli mění, nebo ovládá velkou síť počítačů s různými adresami (botnet), ochranu vám pohodlně obejde.

Mazání duplicit

Další poslední záchrana. Normální člověk vám do knihy nenafláká deset navlas stejných vzkazů. Maximálně tak dva, když se uklikne, a i tak je ten druhý zbytečný. Takže můžeme každý nový příspěvek porovnat s několika předchozími a pokud se s některým shoduje, zahodit ho. Nevýhoda je, že roboti svoje bláboly většinou aspoň nepatrně obměňují.

Na závěr...

Nebojte se, není to tak horké. Spammeři si umí spočítat, kolik práce se jim ještě vyplatí vynaložit a kolik už ne. Nejvýhodnější je hacknout nějaký hodně rozšířený systém (jako třeba fórum PHPBB nebo návštěvní knihy od Blueboardu). Potom se ještě vyplatí zaspamovat nějaké velké a často navštěvované servery. Zbytek světa a amatérské stránky s jednotkami až desítkami návštěv za den už jim nestojí za individuální námahu. Raději si budou piplat svoje univerzální roboty, kteří zvládnou zaneřádit dostatečné množství dostatečně málo zajištěných stránek, ale na celý internet zatím nestačí.

A to je vše, přátelé!

Ještě bychom si mohli probrat mazání vzkazů z knihy, ale pro začátek si vystačíte s administračním rozhraním MySQL a časem vás určitě napadne, že se u každého příspěvku dá zobrazit nenápadný odkaz s jeho idčkem a nějak vhodně ho využít už by mělo být celkem jednoduché. Jestli ne, počkejte si na příští díl, kde si sestrojíme pořádné fórum s vlákny, registrovanými uživateli a administrátorským rozhraním.


 

  Aktivity (1)

Článek pro vás napsal Mircosoft
Avatar
Autor je amatérský pascalista, assemblerista a bastlíř. Profesionálně psal nebo píše v HLASM, Rexxu, Cobolu, ST, LAD, FBD, PHP, SQL, JS, Basicu a pár dalších jazycích, které kupodivu stále existují a používají se :-).

Jak se ti líbí článek?
Celkem (8 hlasů) :
55555


 



 

 

Komentáře
Zobrazit starší komentáře (2)

Avatar
Kit
Redaktor
Avatar
Kit:

V principu je každý předaný parametr typu text. Některé z nich se dají vyhodnotit i jako číslo, jiné jako datum nebo čas, boolean, seznam, a kdovíco ještě.

Odpovědět 8.9.2012 10:33
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Petr Hanzal :

Výborný seriál! Základy PHP jsem se naučil právě tady.

 
Odpovědět 10.8.2013 8:09
Avatar
David Hynek
Redaktor
Avatar
David Hynek:

Nevím jestli používáte datové schránky, ale tam mají jako potvrzovací kód cca 3 čtyřciferná čísla, která se stále opakuji.

Odpovědět 10.8.2013 9:09
Čím víc vím, tím víc věcí nevím.
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Hynek
Kit:

Datovou schránku sice nepoužívám, ale mám už s nimi dost zkušeností. Názorná ukázka, jak šíleně se dá zprasit webmail.

Odpovědět  +1 10.8.2013 10:16
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
lubos.blader
Člen
Avatar
lubos.blader:

Zdravím. Zdrojový kód nebude?...

 
Odpovědět  -1 27.3.2014 20:04
Avatar
Odpovídá na lubos.blader
Ondřej Štorc:

Rychle jsem si pročetl článek a podle mně není potřeba. Je napsán tak aby lidem poradil a ne aby jim to vše udělal..

Odpovědět  +2 27.3.2014 20:21
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
Odpovídá na lubos.blader
Michal Žůrek (misaz):

k čemu? Všechen potřebný kód je v článku se zvýrazněnou syntaxí.

Odpovědět 27.3.2014 20:38
Nesnáším {}, proto se jim vyhýbám.
Avatar
lubos.blader
Člen
Avatar
Odpovídá na Ondřej Štorc
lubos.blader:

Som úplný začiatočník v PHP. A oveľa lepšie sa učí vo fungujúcom kóde, ako keď ho píšete komplet celý, nefunguje a netušite kde je chyba, ktorá môže byť úplne inde. Napríklad, a to som už zistil, v rozdielnom pripojení k databáze.

 
Odpovědět 27.3.2014 21:29
Avatar
Mircosoft
Redaktor
Avatar
Odpovídá na lubos.blader
Mircosoft:

Stažitelný zdroják přímo k tomuhle článku nemám, ale můžeš si stáhnout hotovou návštěvní knihu: http://mircosoft.mzf.cz/…load/php.zip . Není to přesně totéž, ale je tam hodně společných prvků.

Editováno 28.3.2014 20:08
 
Odpovědět 28.3.2014 20:07
Avatar
lubos.blader
Člen
Avatar
Odpovídá na Mircosoft
lubos.blader:

Ďakujem. Už som sa cez to prehrýzol. Pekný článok. Pekný deň prajem.:)

 
Odpovědět 29.3.2014 9:26
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 12. Zobrazit vše