Newsgroup: it.comp.www.php
Titolo: Per eviare la chiamata diretta di pagine interne

Ciao a tutti
ho una pagina php che deve essere rigorososamente chiamata solo da una 
particolare pagina precedente che passa tutte le vatriabili con un form.
Per fare questo io lancio un cookie dalla pagina chiamante e la pagina 
chiamata lavora solo se il cookie c'è.
Purtroppo alcuni utenti non accettano i cookies
Affinchè l'utente non chiami da se una pagina come posso fare?
Grazie

Paolo ha scritto:

controllare il referer della pagina ?

Affinchè l'utente non chiami da se una pagina come posso fare?
Sbagli candeggio :-)
Devi fare in modo che la pagina funzioni anche se non e' chiamata dalla
tua form (in quel caso ovviamente non deve fare niente).
Se il tuo sistema RICHIEDE che solo quelle due pagine comunichino, vuol
dire che c'e' un errore[1] di progettazione da qualche parte.
In mancanza d'altro, aggiungi uno "pseudo cookie" crittografico, usando
un campo hidden (questo introduce altri problemi, come tutto).
Leonardo
[1] almeno per come definisco io gli errori :-)
-- 
While ordinarily valid that being widespread does not make a statement
true, I feel that the diffusion of anti-evolutionary beliefs does pose
a strong argument for Darwin having been, indeed, sorely mistaken.

 un form.
Per quale motivo hai questa necessita'?
Che cosa cerchi di ottenere?
-- 
Vuoi distribuire il tuo sito web su CD/DVD?
Prova 
http://www.dwebpro.com/
Vuoi diventare un esperto analista PHP/MySQL?
Vieni a fare uno stage con noi: 
http://www.creativepark.it/stage/


in questa pagina salvo i dati del form su di una tabella mysql e cercavo di 
evitare l'inserimento di dati inviati da locale 

Paolo ha scritto:

...??? cioè... vorresti evitare che qualcuno scriva uno script che 
chiami centinaia di volte quella pagina e inserisca quello che vuole 
lui? tipo cross-scripting? tipo i rompiballe che spammano nei guestbook??
una via potrebbe essere questa:
nella prima pagina, prima o dopo il form, dai valore ad una variabile di 
sessione, tipo:
$_SESSION['controllo']='sono io apri!!';
poi nella seconda pagina metti un controllo tipo:
if ($_SESSION['controllo']=='sono io apri!!') {
   esegui tutto quello che vuoi...
} else {
   echo 'vai a cagare spammatore di merda...';
}
che ne dici?

 che ne dici?
Ottimo ma se i cookies sono disabilitati?
Che fine fanno le variabili della sessione?
Poi $_SESSION['controllo']='sono io apri!!'; si può fare anche da locale o 
no?

Paolo ha scritto:

Se il browser non ha i cookie abilitati puoi inserire il SID in una 
stringa di query oppure in qualche campo nascosto di un form....vedi 
pure trans_id nel php.ini

 
Necessiti una studiatina al funzionamento delle sessioni...
se i cookie sono disabilitati le sessioni si propagano tramite la 
variabile PHPSESSID che (a seconda di come è configurato il server, il 
php.ini o i tuoi script...) passa, ad esempio, come aggiunta ai link. 
ovvero 
www.miosito.it/index.php
 diventa 
www.miosito.it/index.php?PHPSESSID=fdafepr3e0e099d0fad9f9dasfaafa
o viene buttato direttamente come campo hidden nei form.
Comunque... se usi bene session_start() ecc... l'id di sessione passa 
anche senza i cookie. Coi cookie è meglio, ma ce ne sbattiamo le balle!! 
(o... se vuoi puoi anche dire che senza cookie abilitati non si 
lavora... però rischi di perdere visitatori!).
Poi...
le variabili $_SESSION sono delle variabili php e si possono impostare 
solo da dentro lo script php. qualche rischio lo corri solo se lavori 
con register_globals in on (ma chi attenta dovrebbe conoscere il nome 
della variabile!).
se devi lottare con gli spammer datti una letta al numero di turing (o 
touring??)

Paolo ha scritto:

Se lo script contenente il form e quello di inserimento dei dati sono
accessibili senza alcun tipo di protezione/autenticazione, allora per
un utente esperto sara' sempre possibile automatizzare l'invio dei dati
"da locale" (es. utilizzando fsockopen, cUrl, etc). L'utilizzo di
sessioni o cookie aggiungera' un livello di protezione piuttosto
blando, in quanto entrambi i sistemi sono facilmente "riproducibili"
(e' sufficiente richiamare la pagina con il form tramite le funzioni
cUrl, e con la stessa sessione richiamare la pagina di inserimento).
Puoi valutare la possibilita' di creare un sistema di autenticazione
che protegga l'inserimento dei dati con username/password e/o
aggiungere un sistema tipo captcha per evitare una completa automazione.


 cUrl, e con la stessa sessione richiamare la pagina di inserimento).
E' proprio quello che si vuole ottenere, cioè passare prima dal form e
poi arrivare alla pagina di inserimento dati.
Aggiungo al fatto di usare le sessioni l'utilizzo di codice captcha
inserito nella pagina del form e da verificare nella pagina di
inserimento dati;
Ciao,
     Fabrizio
--website: 
http://www.negusweb.it

"da locale" (es. utilizzando fsockopen, cUrl, etc).
No, non necessariamente.
Il form di inserimento viene generato dalla pagina "A", includendo anche
un token di validazione unico e non riproducibile da terzi (per esempio,
md5($secret . ':' . uniqid('')) ) in un campo hidden. La pagina "A" poi,
in sessione oppure in una tabella del database, inserisce il token e una
timestamp (questo nel caso del database, per poterlo "ripulire" dai vari
tentativi fatti dal robottino di turno: DELETE... WHERE creation < ...).
A questo punto l'utente invia il form compilato alla pagina "B", che non
deve fare altro che verificare che il token sia registrato in sessione o
esista nel database. Lo cancella e approva l'inserimento.
Il caso successivo (per molti versi diverso!) in cui tutto il giro viene
fatto da un robot, che quindi VISITA DAVVERO la pagina "A", e poi visita
DAVVERO la pagina "B", lo si puo' affrontare con captcha oppure con JS o
modificando opportunamente i campi (per esempio si puo' generare una map
fake_random_name -> real_field_name e salvarla in sessione. A quel punto
il robot non sa in quale campo, per esempio, inserire il CAP - dentro al
campo asdf1824 o dentro al campo uiop374? Con i CSS si puo' fare in modo
che non possa servirsi della dimensione del campo. E se nel campo CAP e'
presente qualcosa di diverso da cinque cifre, il form e' non valido).
Leonardo


 diverso da cinque cifre, il form e' non valido).
Quest'ultimo metodo aumenta solamente la complessita' della logica
applicativa senza realmente migliorarne la sicurezza.
Se un utente e' in grado di compilare il form (escluso il captcha e
simili) semplicemente leggendo le etichette dei campi per capire dove
deve inserire i valori, sara' sempre possibile creare un bot ad hoc che
ne possa riprodurre il comportamento, per quante modifiche vengano
fatte alla form lato server e/o lato client.
Esistono molti tool che permettono l'automazione, ad esempio comandando
Internet Explorer tramite automation. In questi casi una soluzione
tramite JS verrebbe bypassata come niente fosse.


Date un vostro giudizio per favore ad una prima implementazione di prova per 
evitare un possibile robot
nella pagina A che contiene il form inserisco all'inizio
<PHP
session_start();
$_SESSION['key']='true';
?>
all'interno del form
<?PHP
if(!IsSet($_COOKIE['PHPSESSID']))
{print("<INPUT TYPE=HIDDEN NAME=PHPSESSID VALUE=$PHPSESSID>");}
?>
Nella pagina che riceve il form
<?PHP
session_start();
if ($_SESSION[key]!=='true')
{
$_SESSION['key']='';
header('Location: http://www.pincpčallino.it/paginabianca.htm');//vicolo 
cieco
exit();}
$_SESSION['key']='';

applicativa senza realmente migliorarne la sicurezza.
Non sono d'accordo: e' vero che la logica applicativa si complica (nulla
si ottiene per nulla, in questo mondaccio), ma non ti serve password (il
che semplifica le procedure di registrazione, che magari ora non ci sono
neanche).
E, per violarla, ti serve un BOT che interpreti CSS e Javascript. Io, ad
oggi, non ne conosco. Sicuramente e' possibile scriverli; ma ne varrebbe
la pena - per lo spammer?
A quel punto al padrone del bot forse conviene... anziche' sviluppare il
bot che poi, comunque, serve per quel sito li' e basta (a meno di volere
creare un ancor piu' complesso bot generico)... sub-appaltare il compito
di compilare le form a una body farm in Bangladesh.
Immagino che tutto dipenda dal valore assegnato, da un lato, al 'botter'
alla compilazione di *quel* form, e dall'altro, da Paolo al non avere il
form riempito da un bot.
Per altro, OK, il discorso si e' spostato sui bot, ma originariamente si
parlava - o cosi' m'e' parso - di un problema diverso.
Suppongo che forse faremmo meglio a chiedere piu' dettagli a Paolo circa
il problema, anziche' cercare di risolvere due problemi diversi fra loro
(quel che tu hai capito, e quel che io ho capito), che magari sono anche
diversi dal problema reale.
Buon anno,


 Leonardo
Il problrmsa č ed era
Se un programma e non un essere umano chiama ripetutamente una pagina 
(passando dati realistici) che mi serve a salvare i dati di un form che 
provengono da un form posto in una pagina precedente io mi troverei la 
tabella mysql piena di scarafaggi.
Naturalmente ho protetto contro il salvataggio di records vuori quindi per 
farlo bisogna che il programma passi dei dati realistici o che addirittura 
lanci i dati dalla pagina in cui risiede il form
Sono d'accordo con te che ne deve valere la pena .
Per quanto riguarda una EVENTUALE CHIAMATA ALLA PAGINA DI SALVATAGGIO HO 
FATTO COSě:
nella pagina A che contiene il form inserisco all'inizio
<PHP
session_start();
$_SESSION['key']='true';
?>
all'interno del form
<?PHP
if(!IsSet($_COOKIE['PHPSESSID']))
{print("<INPUT TYPE=HIDDEN NAME=PHPSESSID VALUE=$PHPSESSID>");}
?>
Nella pagina che riceve il form
<?PHP
session_start();
if ($_SESSION[key]!=='true')
{
$_SESSION['key']='';
header('Location: http://www.pincpčallino.it/paginabianca.htm');//vicolo
cieco
exit();}
$_SESSION['key']='';
Mentre nel caso che venisse chiamata la pagina contenente il form pensavoi 
che il tuning fosse la maniera migliore ma non so che fare a proposito 
perche mi sembrano metodi troppo complessi per il grado di sicurezza 
occorrente nel mio sito e vorrei che fosse sempolice ma efficiente
Grazie e naturalmente buon anno

 spammer?
Dipende da quali dati saranno inseriti e quale uso ne fara' il sito, lo
spamming e' solo una dei possibili utilizzi. Se, ad esempio, il sito
permettesse di creare delle pagine o dei contenuti visibili a tutti a
partire dai dati inseriti nella form, potrebbe venire utilizzato per
azioni di phishing e probabilmente ne varrebbe la pena per l'attaccante.


azioni di phishing e probabilmente ne varrebbe la pena per l'attaccante.
Vero... ma in un caso come questo il sito sarebbe gia' protetto con una
password, e l'upload ristretto ai soli utenti registrati e validati (se
poi uno da' l'account in automatico a cani e porci, penso che abbia dei
problemi piu' urgenti e importanti dei robot).
Il 'page mangling' serve soltanto nel caso di una form ad accesso molto
ampio, in cui si voglia discriminare fra umani e robot - o fra onesti e
gente che magheggia con i valori in submit - senza "pesare" sull'utente
finale. Non volevo suggerirlo come soluzione finale universale :-)
Leonardo IHHO


tabella mysql piena di scarafaggi.
OK. Ma tutto dipende da cosa c'e' in quel form e da quali feature puoi
aspettarti dai tuoi client, e dai robot.
Mi spiego: se sei sicuro che i tuoi client usino tutti Javascript, e i
robot no, allora ti basta mettere un campo hidden "check" che vale 0 e
impostarlo a 1 via Javascript. I robot avranno check=0 e li riconosci.
Ma cosi', un utente con JS disattivato si vede rifiutare. Puoi mandare
un avvertimento, o forzare il submit solo via Javascript, se questo e'
accettabile (non e' detto che lo sia).
Oppure puoi supporre che i robot non "renderizzino" la pagina, e cosi'
non distinguono fra campi visibili e invisibili. Metti un campo text -
invisibile - con un nome succulento, tipo "email", e l'eventuale campo
email della form lo chiami "nictalopo". Allora noterai che le form dei
robot hanno qualcosa nel campo email, quelle degli utenti veri che non
possono vedere il campo email saranno vuote.
Tutto questo NON ti difende dal caso di un utente che, a mano mano o a
mano usando un macro recorder, rifaccia ogni volta il giro... li' devi
trovare un altro sistema. Per esempio: "un utente, un form". Pero' per
farlo devi poter distinguere gli utenti, il che vuol dire user e pass,
che a volte e' una complicazione.
Senza user e pass, siamo chiari: il caso dell'utente fully manual *NON
LO BATTI* (puoi limitarlo con controlli sull'IP). Puoi, forse, sperare
di battere il macro recorder - SE hai idea di come funziona. Per dire:
se il macro recorder preme sempre il tasto con scritto INVIA, potresti
pensare a scriverlo " INVIA", "INVIA ", "I N V I A" a caso. Oppure con
un cronometro, se per riempire il form uno ci mette meno di 20 secondi
lo consideri un robot (salvi il timestamp di invio in sessione, poi te
lo rileggi al submit).
Ma IN ASTRATTO e' difficile suggerirti una strategia, perche' vorrebbe
dire che esiste una "formula vincente" - e non esiste. Ogni caso e' un
caso diverso.
Quello che posso fare e', se mi fai vedere cinque o sei submission che
ritieni "robotiche", provare a dedurre come funziona QUEL robot, e poi
immaginare una strategia che funzioni in QUEL caso.
Ti dico, io in genere noto OTTIMI risultati con un sistema banale - ma
banale banale, veramente rozzo! - che e' quello di chiamare "email" il
campo "Subject", e "Subject" il campo "email".
I robot che ho visto passare io immancabilmente o mettono tutti quanti
i campi uguali, o mettono ritorni carrello a catapetere per l'email, o
mettono una pseudo email nel campo subject [1].
Quindi mi basta controllare che il campo Subject sia una email valida,
diversa dal campo email, e che nessuno dei due contenga "\n" -- e gia'
questo STUPIDISSIMO sistema ferma tutti gli (evidentemente ancora piu'
stupidi) robot che ho visto passare finora.
Ovviamente NON fermera' *MAI* un attaccante umano appena piu' furbo di
una scimmia, ma questo caso per ora non m'e' capitato.
E quando vedo passare un robot, gli mando per risposta una pagina dove
dice "OK! I suoi dati sono stati registrati!"... e cosi' SPERO che non
segnali neanche di aver incontrato problemi a un eventuale supervisore
umano, che, se sapesse che esisto, potrebbe fregarmi facilmente.
Leonardo
[1] sono robot da macchine zombizzate, che lavorano sui grandi numeri:
    oltre ai miei siti ne spazzoleranno altri dieci milioni. Come dice
    il proverbio, se sei una gazzella, non devi correre piu' veloce di
    un leone... ti basta correre piu' veloce della gazzella piu' lenta
    del tuo branco.


 banning di anonimizzatori, rate limiting.
Anche questa "sicurezza" e' facilmente aggirabile utilizzando proxy etc.


Anche questa "sicurezza" e' facilmente aggirabile utilizzando proxy etc.
Ma siamo d'accordissimo. L'unico sistema sicuro e' l'AOS (Ass-print Over
Shoes, cioe' viene l'utente da te a piedi e ti lascia impronta di culo -
e anche li', prima o poi riusciranno a clonare l'essere umano e saremo a
capo :-) ). O detta meno alla buona: "il sistema sicuro non esiste".
Sicche' ha poco senso, credo, sottolineare il fatto che ogni sistema sia
fallato. Per forza lo e'... se esistesse il sistema perfetto, e privo di
difetti (compresi costo/difficolta'/ecc.), userebbero tutti quello, no?
Quel che voglio dire e' che _secondo me_ ha senso valutare la sicurezza,
in un'ottica di costi/rischi/benefici: mi serve *davvero* un sistema che
puo' fermare i terroristi ceceni, se poi alla prova dei fatti quello che
mi arriva sulla pagina web e' un bot calibrato su cinque o sei form tipo
facilmente exploitabili - e abbastanza diversi da quelli che uso io?
In un caso simile mi basta quel minimo di sicurezza perche' il bot passi
oltre, senza implementare tutte le misure di sicurezza possibili.
Soprattutto se implementare queste misure di sicurezza mi produce disagi
non solo a livello di server/programmatore (per scrivere il codice o per
lo meno installarlo, ecc.), ma anche a livello di utenti (che devono - a
seconda dei casi - usare solo browser XY-capable, oppure con Javascript,
oppure crearsi un account, o mandare fotocopia di un documento...)?
Per quel che ho capito, finora, del problema di Paolo, ha a che fare con
uno (o piu') form-bot di tipo generico su una form senza autenticazione.
Certo - se poi salta fuori che ha fatto incazzare l'ex KGB, gli daro' un
consiglio completamente diverso: magari, chiudere il sito per mettersi a
vendere spazzole porta a porta, e dimenticarsi proprio di Internet.
(Mi rendo conto che non dico niente di nuovo da vari post. Non lo faccio
per testardaggine o stupidita' (almeno, io spero di no!), ma davvero: su
questo argomento non ho altre cose da dire... ho fornito i miei canonici
0.02 EUR, tant'e', nella scarsella non avevo altro)
Buon anno,
Leonardo


 troverei la tabella mysql piena di scarafaggi.
Scarica KCAPTCHA ed integralo nel tuo script (e' molto semplice, basta
seguire l'esempio):
http://www.captcha.ru/en/kcaptcha/
Questo ridurra' i possibili attacchi di sistemi automatici.


I ruoi mi sembrano ragionamneti giusti e nella semoplicità vedo infatti una 
buina difesa che penso potrebbe essere ottima se si aggiunge un occhiata al 
referer come suggerito da Ext2 che potrebbe dare la certezza che la chiamata 
ad una pagina è stata fatta dal server e non da locale.
Siete d'accordo?

 server e non da locale.
Alcune note sull'header referer:
- Non tutti i browser lo impostano.
- Alcuni proxy e firewall lo eliminano o lo modificano.
- E' facilissimo da forgiare.
In pratica rendi l'applicazione piu' difficile se non impossibile da
usare per alcuni utenti (es. quelli dietro a certi firewall e proxy)
senza aggiungere molta sicurezza.


controllare il referer della pagina ?
Ho provato il tuo suggerimento come segue:
if ($_SERVER['HTTP_REFERER']!=="
http://www.pincopallino.it/form.php
")
{ header('Location: 
http://www.pincopallino.it
');
exit();}
è insieme ad altre protezioni e mi sembra che funzioni tutto bene
Potresti suggerirmi qualche cosa di più elastico (stand alone) da inserire 
in tutte le pagine pericolose ma che purtroppo sono chiamabili da più pagine 
e dallo stesso menù e non come nel caso di cui sopra che era chiamabile solo 
da form.php?
Grazie

Certo che con tutta la brama di sicurezza che gli utenti vogliono da parte 
dei browser ci si è dimenticati di dare altrettanta sicurezza ai siti.
Mi sembra di vedere le leggi dello stato tanto difensive nei confronti dei 
delinquenti (poverini) e tanto meno nei confronti dei non delinquenti

Siete d'accordo?
Tieni presente che il referrer non e' granche' affidabile, il controllo
del medesimo e' abbastanza diffuso "di serie" in vari pacchetti... e la
sua simulazione e' facilissima.
Quindi IMHO e' elevato il rischio che i bot lo simulino di gia', giusto
per principio (basta salvarlo una volta, o andare a caso e mettere come
referer lo stesso sito: parecchi pacchetti controllano solo questo... e
ti risparmi una chiamata di pagina web, il che potenzialmente raddoppia
la quantita' di form che il bot puo' mandare).
E in piu', come ti fa notare Filippo - io me n'ero scordato, confesso -
alcuni "personal firewall" eliminano il referrer anche quando e' uguale
al sito visitato [cosa IMHO demenziale, ma e' vero, c'e' chi lo fa], e,
se uno dei tuoi visitatori ne fa uso, a quella disgrazia ci aggiungi il
non poter compilare il tuo form :-D
Credo meglio impostare un valore ogni volta diverso in un campo hidden,
salvarlo in sessione e e rileggerlo in sede di submit... la "sicurezza"
ovviamente e' zero contro un bot scritto ad hoc, ed anche contro un bot
che si spazzoli DAVVERO tutt'e due le pagine. Ma e' probabile che nella
maggior parte dei casi i bot lo facciano solo la prima volta... o anche
mai.
E a implementarlo ci metti veramente due minuti due.
Ancora un po' meglio mettere nel valore nascosto il timestamp, cosi' da
poter calcolare quanto ci ha messo il tizio a compilare il form - sotto
a un certo tempo, _non puo'_ essere un essere umano; e sopra a un altro
tempo, neanche: e' un bot che usa valori salvati molto prima.
(Magari non partire subito di vaffanculi: magari e' un essere umano che
ha cliccato subito su INVIA :-) )
...nella prima pagina...
	$_SESSION['startform'] = time();
...nell'altra pagina...
	$elapsed = time() - (isset($_SESSION['startform']) ?
		$_SESSION['startform'] : 0;
	if (($elapsed < 10) || ($elapsed > 3600))
		$really_SQL = false;
	else
		$really_SQL = true;
	...
	/* Praticamente se pensi che sia un bot, fai tutto normalmente,
	   ma l'inserimento nel database non viene effettuato.
	   Nell'improbabile caso che il botter tenga dei log, il tuo si
	   smarrira' fra gli ennemila siti exploitati con successo.
	   Non e' probabile, nient'affatto: ma forse C'E' un botter che
	   se lo sfanculi te la giura. E forse lo becchi proprio te. Io
	   direi che sia meglio non far nulla per farsi notare :-D
	*/
	if ($really_SQL)
	{
		SQLExec("INSERT INTO tabella ...");
	}
Anche qui, teoricamente e' facile per un bot mantenere una lista con le
form "outstanding" e inviarle dopo un ritardo - ma in pratica non credo
che qualcuno "perda tempo" a scrivere bot cosi' complicati, quando c'e'
uno zilione di form piu' vulnerabili in giro.
(Tra l'altro uno che ha un form poco vulnerabile e', evidentemente, uno
che un minimo ci tiene: e che, se anche gli exploiti il form, tempo due
o tre giorni ha tappato il buco o tolto il form. Quindi non c'e' troppo
sugo nel cercare di sfondare a tutti i costi: e' meglio concentrarsi su
quel 30-50% di capre che tengono tutto aperto, e anche DOPO che gli hai
segnalato che li hanno aperti come cozze, non fanno niente [1]. Li' si'
che c'e' susta).
Leonardo
[1] idem per il phishing... vado a riguardare i siti phisciosi del MESE
    SCORSO, e i due terzi buoni, non scherzo, sono ancora li' beanti.


dei browser ci si è dimenticati di dare altrettanta sicurezza ai siti.
Ehi, sei TU quello che deve dare sicurezza al tuo sito :-D
