PDA

Pogčedajte punu verziju : Prazan $_SERVER['HTTP_REFERER']


bluesman
09. 11. 2005., 02:40
Problem: Sistem privatnih poruka. Na sajtu postoji formular, pisu poruku i kliknu na send. U scriptu koji cuva poruke u bazu stoji ovako nesto:

if (!eregi($_SERVER['HTTP_HOST'], $_SERVER['HTTP_REFERER']))
die ("no spam");

To je da bih sprecio da se uloguju pa onda sa nekih drugih servera salju gomila poruka (desava se da neki posalju i po 800-900 poruka za par sati). To uglavnom rade oni nigerijci budale koji traze pare i spamuju.

Medjutim, naizgled jednostavno resenje ima problem. Nekim clanovima je referer prazan. Znaci $_SERVER['HTTP_REFERER'] == ""

Kako je to moguce? Razliciti su browseri u pitanju a korisnici su sve samo ne strucni da umeju da sakriju referer na neku foru.

Milos Vukotic
09. 11. 2005., 08:47
Mislim da je caka u firewall-ovima...

Petar Marić
09. 11. 2005., 09:25
U prevodu ti imaš probleme sa CSRF (http://www.squarefree.com/securitytips/web-developers.html#CSRF)?

E sad davno je bilo kad sam se zanimao time u php-u. U osnovi šalješ jedan skriveni parametar kroz forme/url/sesiju/kolačić čija vrednost je validna samo za taj zahtev.

Da koristiš django, mogao bih ti preporučiti CsrfMiddleware - simple Cross Site Request Forgery protection (http://lukeplant.me.uk/resources/csrfmiddleware/index.html) :rolleyes:

srdjevic
09. 11. 2005., 16:16
Meni se desilo da sam kod drugara naleteo na njegov FireFox koji je slucajno podesen da salje $_SERVER['HTTP_REFERER'] = 'HTTP_REFERER';
pa mi neke redirekcije nisu radile... :-(

Znaci, ima i takvih slucajeva.

bluesman
09. 11. 2005., 16:36
Petre, hvala za link, medjutim to je definicija problema a ne rešenje :)

Što se tiče skrivenih parametara, ne znam kako si to mislio, da stavim neki "hidden"? To i nije zaštita, a $_SESSION, i $_COOKIE ostaje jer je on ulogovan. Kapiraš šta rade? Dođu na sajt i samo se uloguju. A onda sa svog servera šalju post zahteve na script koji šalje poruke i pošto su ulogovani ovamo, stoji im lepo i SESSION i COOKIE, tako da prođe bez problema. A to se iz javascripta relativno lako uradi... samo napraviš da fura neki array sa id-jevima članova i na load, šalje sledeći... nije neka nauka :)

Ilija Studen
09. 11. 2005., 16:57
Prosta CAPTCHA? Znam da smara korisnike, ali ako im jasno naglasiš da je to tu da bi zaštiti njih od spam poruka mislim da će razumeti. 3 cifre je sasvim dovoljno u tvom slučaju IMO.

Što se referera tiče može da se blokira slanje istog jako lako. Čak većina alternativnih browser, pogotovo IE ljuski ima ugrađen "paranoid" mod (ime mu govori sve ;) ). I sam znaš kakvi su obični korisnici... Pročitaju u Mikru kojekakve priče i onda od mrava prave slonove ;)

PS: Za one koji ne znaju šta je CAPTCHA (http://en.wikipedia.org/wiki/Captcha).

dinke
09. 11. 2005., 17:53
Mozes i sam da generises referer i da ga ubacis u promenljivu sesije.

Recimo na prvoj strani nesto tipa:
$_SESSION['referer'] = $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

A na sledecoj:
if (!eregi($_SERVER['HTTP_HOST'], $_SESSION['referer']))
...

Bitno je samo da prvo proveris referer a tek setujes nov u sesiji ili kukiju.

Inace, ja bi umesto captche generisao neki hash baziran na username/pass kompbinaciji i ubacio ga u sesiju, a istu proverio na sledecoj strani. Na primer na strani sa koje si zeleo da uzmes referer:

$_SESSION['hash'] = md5($_SESSION['username'].$_SESSION['pass']);
a na sledecoj:
if($_SESSION['hash'] == md5($_SESSION['username'].$_SESSION['pass']))
...

Naravno, mozes staviti bilo sta, ne mora username / pass.

Petar Marić
09. 11. 2005., 19:52
@bluesman: Nešto si rek'o :p
Sadržaj preuzet sa već pomenute stranice (http://www.squarefree.com/securitytips/web-developers.html#CSRF)
Preventing CSRF


Make sure that the cgi that handles form submissions for forms that change server state only accepts POST parameters, not GET parameters. Some server-side languages default to accepting both.
Make sure form submissions use your own forms by including a hidden field that is an MD5 hash of the login cookie and a secret on the server. Then only accept the form if the hidden field is correct.
Optional added paranoia: Add a timestamp as a hidden field and include it in the hash. Make the form expire if the timestamp is too old. Give users a way to submit the form again when the form expires, such as by returning the form pre-filled with the data they entered last time but with a fresh hash. Do not rely on the Referer header to protect your visitors from CSRF. (Browser bugs (http://bugzilla.mozilla.org/show_bug.cgi?id=26257#c24) and features (http://bugzilla.mozilla.org/show_bug.cgi?id=141641) allow web sites to create referrerless links, so you would have to reject referrerless form submissions. Some users choose to turn off referers, so you can't protect these users without preventing them from accessing your site at all. Some users even spoof their referer so it always appears to come from the site they are requesting a page from, making them impossible to protect in this way. Users that spoof referrers usually do so in order to access porn sites that restrict access to content solely based on referers.)
Since so few sites protect their visitors against CSRF attacks, we have discussed possible client-side fixes for CSRF. We didn't come up with anything good. For reference, see bug 38933 (http://bugzilla.mozilla.org/show_bug.cgi?id=38933), bug 40132 (http://bugzilla.mozilla.org/show_bug.cgi?id=40132), bug 246476 (http://bugzilla.mozilla.org/show_bug.cgi?id=246476), and bug 246519 (http://bugzilla.mozilla.org/show_bug.cgi?id=246519). At most, browsers might be able to prevent CSRFs from web sites to intranet sites, but not between web sites.


Naravno dodatak CAPTCHA-e samo ulepšava rešenje, mada ti preporučujem da dodaš i proveru minimalnog intervala između slanja 2 poruke.

Edit: Čisto da napomenem, ako neki nisu do sada shvatili: Za svaku formu koja menja stanje (aka state) na serveru se koristi dotična kombinacija - naravno tajni ključevi se menjaju za svaki novi zahtev.

noviKorisnik
09. 11. 2005., 23:47
Ne razumem jedno - želiš da sprečiš postovanje s drugog sajta - ok - a kako izlaziš na kraj ako dođe na tvoj sajt i odatle odradi malo spamovanje od 700 PP?

bluesman
10. 11. 2005., 00:09
Pa to mu se ne isplati :) Mnogo dugo traje, oni ne rade to tako.

noviKorisnik
10. 11. 2005., 01:02
Kako im ipak predstavlja napor da na svom serveru odrade skriptu za utovar, isti posao može da se odradi i s klijentske strane. Na klijentu može da se modifikuje stranica - primer - doda se iframe, promeni target formulara na taj iframe, i čak uglavi skripta za cirkularno prosleđivanje formulara - dok ti redovno primaš da je referer s tvog sajta ;-)

(uglavnom, lepa je tema, moram na spavanje... nastaviću se kasnije)

oliver
10. 11. 2005., 01:17
Naravno dodatak CAPTCHA-e samo ulepšava rešenje, mada ja savetujem da dodaš i proveru minimalnog intervala između slanja 2 poruke.

Blues, zasto ne ovo ^?

bluesman
10. 11. 2005., 01:55
@oliver: Pa to je za sada najočiglednije rešenje...

@noviKorisnik: mislim da te nisam razumeo šta pokušavaš da kažeš.

GET -> POST nije nikakvo osiguranje. Ko spamuje, njemu je sve jedno :) (iako je sve kod mene vec POST)

Znači, ona kada treba da pošalje poruku, mora da kline na "new message" gde mu izađe formular. Neki predlažu da tu dodam neki "secret" code u session koji proveravam kada klikne na "send".

Ja sam čak nešto razmišljao da encrypt-ujem podatke, dovoljno je samo username primaoca koji se encryptuje nekim ključem...

noviKorisnik
10. 11. 2005., 09:11
Dakle, "new message" pa izađe formular. A tada stupa na snagu klijentski DOM skripting - dokument može da se prilagodi za potrebe spamovanja (dodavanje ifrejma, targetiranje formulara na njega i automatika za cirkularno submitovanje).

Ovo je samo jedan primer, verovatno postoje jednostavnije metode da ti stigne info da je referer s tvog sajta a da nije sve baš "čisto". Prema onome što sam čitao može eksplicitno da se podesi koja će vrednost referera da stiže na server (ne znam kako tačno, nadam se da ne moram to da dokazujem). Verovatno može dosta da te ojadi i curlovanjem, itd.

...

Ubacivanje intervala između poruka je vrlo pipava stvar koja treba da balansira između ograničavanja potencijalnog spamera i potrebe realnog korisnika za slanjem više uzastopnih poruka. (što znači da je 3 minuta već preterana vrednost, 1 minut bi već mogao da bude dopustiv za korisnika ali spameru već daje prilično komotan prostor).

...

Sve pomenute muke oko hashovanja mi deluju zaludno, jer ako se jednom otvori formular mogu da se pokupe tajne vrednosti koje se tamo pronađu i iskoriste za 800 submitovanja formulara.

...

Rešenje:
Neka se na formularu nalazi vrednost koja može da se iskoristi najviše jednom.

noviKorisnik
10. 11. 2005., 09:16
Ili, uvedi ograničenja na broj poruka dnevno, klasirano:

newbie - max 5
regular member - max 25
trusted member - unlimited

bluesman
10. 11. 2005., 14:52
1 minut za pisanje poruke?
Morao sam da dignem session_lifetime na 15 minuta jer nekima ni 15 minuta nije bilo dovoljno da napisu poruku :) Cak sam im napravio da kada kliknu "send", ako je session expired, ispise im poruku i ostavi im ceo tekst kako su uneli da nebi ponovo k(lju)ucali :)

Problem je u tome sto ja novim clanovima dajem prvih 24 časa unlimited pristupa da vide kako to izgleda (malo makretinga) a kasnije im se resetuje access na FREE, i onda imaju limit od 4 poruke za 12 sati. E sad, ovi spameri se registuju i to što šalju - šalju i prvih par sati.

Hteo sam da ograničim broj poruka dnevno svima, međutim onda sam primetio da neki savim regularni članovi šalju po 80-100 poruka dnevno koje nisu spam. Onda ima onih koji startuju sve što im piše Ž pored profila i šalju svima poruku "ćao ja sam ,... ako si za neobavezan sex - javi se". Iako je to neverovatno glupo, to su ipak sasvim regularne poruke i pošto su VIP članovi imaju pravo da šalju neograničen broj poruka.

Dakle, problemi su višestruki, a rešenje je samo 1 :)

Ja sam čak hteo da AJAX-ujem ali sam posle kraćeg razmišljanja provalio da ne bih ništa time dobio. Hteo sam da ecnryptujem poruke koje se descrypt-uju pred upis u bazu - nisam siguran da je to zadovoljavajuće rešenje jer bih morao da imam promenljive ključeve kao i promeljive varijable koje encrypt-ujem da bi bio siguran.

Najsigurnij rešenje je ono što je neko ovde predložio, da stavim neki kod kao image pa da moraju da ukucaju kod sa slike pre slanja. Međutim to je mega smaranje i tako kažnjavam one koji su tu sasvim regularno, a takvih je ipak 99.5%.

zekica
10. 11. 2005., 16:09
A da stavis taj kod i sliku samo korisnicima u onih prvih 24h?

Mislim da bi tako moglo i da ne bi bilo preveliko smaranje korisnika (a i sam kazes da spameri uglavnom salju te poruke u prvih nekoliko sati).

Ako i vidis nekog VIP korisnika da spamuje, mozes samo i njemu da to ukljucis...

noviKorisnik
10. 11. 2005., 17:54
Bluesman, majstor si da ne pročitaš ono što napišem - 1 minut (ili 3)... minimalno vreme između slanja 2 uzastopne poruke - flood control, čini mi se da se tako zove.

Kao da sam malo dokon, pa ću citirati sebe...
Rešenje:
Neka se na formularu nalazi vrednost koja može da se iskoristi najviše jednom.
Pri svakom generisanju formulara generišeš identifikator formulara - tajni kod servera + id korisnika + tajmstemp - pa se to hešuje, md5uje ili štogod - pa na formular idu hiddeni tajmstemp i generisani identifikator.

Kad se formular prosledi, proveri se:
- da li je tajmstemp stariji od 15 minuta - ako jeste - formular istekao - kraj
- da li identifikator odgovara hešu tajnog koda servera + ida korisnika + tajmstempta - ako ne odgovara - krivotvoreni formular - kraj

Ako nije puklo na ovim proverama, pokušava se upis u bazu. U slogu za upis nalazi se i identifikator formulara koji treba da ide u UNIQUE kolonu tabele, pa
- ako ne uspe upis - spam - ponovno prosleđivanje istog formulara - kraj

Petar Marić
10. 11. 2005., 18:30
Najsigurnij rešenje je ono što je neko ovde predložio, da stavim neki kod kao image pa da moraju da ukucaju kod sa slike pre slanja. Ne bih se složio. Postoji ogroman broj javnih projekata koji pokazuju slabosti CAPTCHA testova.

I dalje smatram da je u ovom unosu (http://www.devprotalk.com/showpost.php?p=2830&postcount=8) izloženo do sada najobuhvatnije rešenje, sve dok mi neko ne dokaže suprotno ;)

Nego sad kad nešto malo bolje razmislim - Gorane zar sistem u kome neki (privilegovani/VIP/etc) član ima mogućnost da pošalje (teoretski) neograničen broj poruka u konačnom vremenskom intervalu bez ograničenja broja poslatih poruka sa strane servera nije u suštini insecure by design?

bluesman
10. 11. 2005., 18:58
U suštini jeste ali to nije suština problema :)

Sir, You're making a scene :)

Ilija Studen
10. 11. 2005., 19:41
Postoji potrebno i dovoljno rešenje ovog problema i mislim da je prilično očigledno i (relativno) jednostavno za implementirati.

Nego Blues, stvarno bi trebalo da poslušaš Petra i staviš neki unbreakable mehanizam u koji ćeš uložiti 4 radna dana. Ionako je programerski sat najbezvrednija stvar na ovoj planeti.

Petar Marić
10. 11. 2005., 19:55
Meh, moje je da pokušam da propagiram inženjerski pristup - na Vama je da odlučite da li ćete me poslušati. Stvar izbora...

Red pill or blue pill, I dont give a f*ck, it's your own funeral anyway ;)

bluesman
10. 11. 2005., 20:32
Evo upravo veceras se desilo ono drugo o cemu sam pricao. Normalan clan, platio clanarinu, i poslao je danas 104 poruke, uvek sa istim tekstom tipa "cao mace, ja sam ... javi mi se na mob. ... hajde da se zezamo".

Tu je sve regularno, ne mogu njega da ogranicavam. Ako njega ne mrzi 104 puta da klikne "new message" pa 104 puta "send" ... to nije moj problem :)

Ilija, jednog dana mora i to da dodje na red. Mozda ne mora da bude unbreakable, ali treba da bude dovoljno tezak da neko bas mora da se pomuci i da odustane pa ode na neki drugi sajt...

Ja razumem petra sta hoce da kaze, ali petre, ovo je specifican sistem. To je specifican community, neki su navuceni totalno, znam sigurno da postoje neki agorofibicni clanovi (strah od kontakta sa ljudima) kojima je to jedini prozor u svet, ima dosta stidljivih kojima je to jedini nacin da komuniciraju, ... vrlo specificna grupa ljudi. Ne mozes tek tako da kazes "max broj poruka dnevno je 100". Verovao ili ne, nekima zivot zavisi o chatu i sms-u.... mnogo je kompleksnije nego sto moze da se ucini na prvi pogled.

Petar Marić
10. 11. 2005., 22:02
Sad se razumemo, whatever pays the bills ;)
BTW, u mom rodnom kraju za takve kažu zagoreli :)

dinke
11. 11. 2005., 00:00
BTW, u mom rodnom kraju za takve kažu zagoreli :)Smejao sam se pola sata kad sam ovo procitao :D

Petar Marić
11. 11. 2005., 01:49
Smejao sam se pola sata kad sam ovo procitao :D
@offtopic: Xex, Dinke ni ti nisi daleko od mog rodnog kraja, kako ih kod tebe vikaju?

bluesman
11. 11. 2005., 13:43
Postavio sam za sada samo kontrolu vremena od poslednje poruke. Stavio sam na 2 minuta, i ako je poslednja poruka mladja od 2 minuta, ne dozvoljava slanje.

Nije resenje problema, ali je bar otezavanje spamerima, samo da vidimo kako ce to da utice na usere, da li ce shvatiti o cemu se radi.