Sicurezza delle sessioni

Malware

Utente Attivo
19 Lug 2012
112
0
0
Salve a tutti
Sto creando delle pagine "protette" per chi esegue il login correttamente.

Io dopo che un'utente ha fatto il login scrivo:
PHP:
session_start();
$_SESSION['username']=$_POST['username'];
Mentre, quando naviga tra le pagina protette scrivo:
PHP:
If (!isset($_SESSION['usermame'])) {
//redirect e messaggio "non sei loggato"
}else{
echo "Benvenuto";
//bla bla bla
}
E' sicuro questo come metodo?
Thanks:)
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
di sicuro in internet non esiste nulla, comunque il metodo è tra i più usati ed è abbastanza sicuro, certo migliorabile ma dipende dall'importanza che hanno le pag protette
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
è un browsergame, quindi abbastanza importante:)

Ma è possibile grazie a qualche modo "alternativo" creare la sessione manualmente?
Poi si mette l'username di un'altro giocatore e patratack:ilpirata:

Thanks:)
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
Ma è possibile grazie a qualche modo "alternativo" creare la sessione manualmente?
le sessioni risiedono (al contrario dei cookie) sul server quindi (non impossibile) ma difficile.
poi se uno conosce l'username di un altro è un altro discorso.
non ti converrebbe usare la password (che tra l'altro, immagino, dovrebbe essere codificata nel db)?
per accedere alla parte riservata che metodo usi? se ti interessa ho un metodo (fatto con l'aiuto di alex) sempre basato sulle sessioni ma più sicuro dagli accessi diretti tipo http : // www . tuo_sito.it / pag_riservata.php
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
si, se mi spieghi di cosa si tratta sono interessato, grazie :)

Per la cosa delle password hai ragione, così sarebbe più difficile. Farò uso del tuo suggerimento!
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
ecco l'esempio di accesso ad una pagina riservata.
sono tre pagine:
1. la pagina che contiene il link con la richiesta di loggarsi (l'ho chiamata partenza.php)
2. la pagina di log che se tutto è ok presenta il form per loggarsi (l'ho chiamata loggati.php)
3. la pagina riservata (l'ho chiamata riservata.php)
il tutto si basa sul principio di creare una session random, che quindi si modifica ad ogni accesso e
verificare se quanto trasmesso dalla querystringa del link (prima nella loggati.php poi nella riservata.php) è uguale alla sessione.
da cui l'estrema difficoltà di accedere, sia al log che alla riservata, se non viene seguito esattamente il percorso partenza -> loggati -> riservata
ammesso che riesca a manipolare la sessione, è molto difficile azzeccare il suo valore codificato trasmesso con il get dato che questo cambia con la sessione ad ogni accesso

partenza.php
PHP:
<?php
if(!isset($_SESSION)){session_start ();}
$_SESSION['p']=rand(1000,10000);//genero un numero random e lo passo in sessione
//oppure al posto della riga sopra
//$_SESSION['p'] = uniqid(mt_rand());
?>
<!-- altre intestazioni -->
<body>
<!-- questa è la pagina di partenza con il link alla pagina di log per accesso a riservata-->
bla...bla...bla...
<p>&nbsp;</p>
<!-- trasmetto la sessione codificata tramite get -->
<p><a href="loggati.php?p=<?php echo md5($_SESSION['p']);?>">admin</a></p>
<!-- altri contenuti -->
bla...bla...bla...
</body>
loggati.php
PHP:
<?php
ob_start();
if(!isset($_SESSION)){session_start ();}
//user e pass provvisorie - poi saranno da ricavare da db
$user="pinco";//da togliere quando si usa il db
$pass="pallo";//da togliere quando si usa il db
echo "<head><title>{$_SESSION['p']}</title></head>";//imbroglio anche sul titolo della pagina, cambia ad ogni accesso
//verifico esistenza sessione, se uguale al get codificato e il nome della pag di provenienza
if(!isset($_SESSION['p']) || md5($_SESSION['p']) != $_GET['p'] || basename($_SERVER['HTTP_REFERER'])!= "partenza.php"){
	//se la pagina che accede a questa non si chiama partenza.php modificare il nome nel basename(....
	//comunque la parte  || basename($_SERVER['HTTP_REFERER'])!= "partenza.php" è ridondante e si potrebbe togliere
	$_SESSION=array();//elimino le eventuali sessioni
	//questo per vedere l'effetto del tentativo di accesso diretto, poi sostituire con l'header location
	echo "tentativo accesso";//dopo le prove commentare o eliminare
	header( "refresh:3;url=partenza.php" );//dopo le prove commentare o eliminare
	//header("location:partenza.php");//dopo le prove decommentare
	exit();
}else{
	echo <<< EOD
<p>per le prove: user = pinco , password = pallo</p>
<form name="form1" method="post" action="{$_SERVER['PHP_SELF']}">
<table width="45%"  border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td width="16%">username</td>
    <td width="84%"><input name="user" type="text" id="user"></td>
  </tr>
  <tr>
    <td>password</td>
    <td><input name="pass" type="password" id="pass"></td>
  </tr>
  <tr>
    <td>&nbsp;</td>
    <td><input name="log" type="submit" id="log" value="log"></td>
  </tr>
</table>
</form>
EOD;
}
if(isset($_POST['log'])){
	//dati di connessione per cercare user e pass nel db - possibilmente sostituire con la PDO
	//require_once "connessione.php";
	//passord con md5 o sah1
	/*
	$user=addslashes($_POST['user']);
	$pass=sah1(addslashes($_POST['pass']));
	$n=mysql_num_rows(mysql_query("SELECT * FROM utenti WHERE user='$user' AND pass='$pass'"));
	if($n == 1){
	*/
	if(addslashes($_POST['user']) == $user && addslashes($_POST['pass'])== $pass){//riga da togliere quando si usa il db
		$_SESSION['p']=rand(1000,10000);//rigenero una nuova sessione random questa non sto a codificarla
		$_SESSION['user']=addslashes($_POST['user']);
		header("location:riservata.php?r={$_SESSION['p']}");
	}else{//pass e username non validi
		$_SESSION=array();//elimino le sessioni
		header("location:partenza.php");
		exit();
	}
}
ob_end_flush();
?>
riservata.php
PHP:
<?php
if(!isset($_SESSION)){session_start ();}
if(!isset($_SESSION['p']) || !isset($_SESSION['user']) || $_SESSION['p'] != $_GET['r']){
	$_SESSION=array();//?? forse meglio distruggere solo la [p] e la [user] nel caso ne avessi altre che mi servono
	header("location:partenza.php");
	exit();
}else{
	echo "<head><title>{$_SESSION['user']}</title></head>";
	echo "ciao ".$_SESSION['user']." sei nella pagina riservata<br>";
	//le righe sotto servono per le prove
	echo "provengo da: ".basename($_SERVER['HTTP_REFERER'])." con vecchio rand<br>";
	echo "la sessione rand è: ".$_SESSION['p']." <br>";
	echo "uguale al get codificato: ".$_GET['r']."<br>";
	echo "<p><a href=\"partenza.php\">esci</a></p>";
	/* e tutto quello che serve sia php che html*/
}
?>
se vuoi usarla però devi modificare la loggati.php adattandola alla ricerca sul db (vedi commenti)
inoltre, se non ho fatto errori di copia incolla, lo scrip l'ho testato e funzia
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
Ciao, grazie per la risposta.
Domani mattina mi leggo bene il codice per capirlo.
Ti faccio un'altra domanda: se ho capito bene, più sessioni creo (quindi più ne controllo per vedere che siano tutte valide) e più difficile sará hackerarle vero?

Ad esempio se imposto due sessioni una con la password cofidicata in md5 dell'user e la seconda con un numero random, sarà molto più sicuro del primo esempio che ho fatto giusto? (creare la sessione username contenente l'username)

Comunque mi sa che useró qualche riga in più per utilizzare il tuo script.

Grazie mille
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
Giusto, perchè sha1 posso anche criptarlo in modo personalizzato.
Allora direi la pass in md5 criptata in sha1.
Ora mi studio il tuo codice, grazieee
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
scusa dimenticavo: fai scegliere o se le assegni tu pass di un certo "spessore" anche eventualmente contenenti caratteri non alfabetici.
es la pass 123456 è comunque sempre facile da baypassare
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
Ehm ho una domandina, la faccio direttamente qui:)

La funzione session_rigenerate_id(); serve per rigenerare l'id delle sessioni.
Ho letto che basta inserirlo dopo il session_start();
E' utile?
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
session_rigenerate_id non fa nulla :)
poi guarda qui a che serve:
http://php.net/manual/en/function.session-regenerate-id.php

però nota uno dei commenti:
Questa può essere una funzione molto pericoloso se non stai attento a come gestire le cose, perché, anche se genera un nuovo set di dati della sessione, mantiene i vecchi dati "aperto" fino a quando lo script termina, bloccando altri script il tentativo di eseguire in concomitanza con l'id di sessione precedente
google translate
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
Meglio lasciarlo lì dov'è allora....fuori dai miei files
Thanks:cool:
 

alessandro1997

Utente Attivo
6 Ott 2009
5.303
1
0
22
Roma
alessandro1997.netsons.org
Il metodo più sicuro per creare un sistema di autenticazione è affidarsi a una libreria di terze parti. Purtroppo la sicurezza è un aspetto talmente delicato di un'applicazione che è molto semplice sbagliare qualcosa, anche se impegnandocisi. Non basta evitare gli errori più ovvi come criptare le password o usare le sessioni al posto dei cookie, altrimenti ogni sito Web del pianeta sarebbe sicuro, quando molto spesso anche i più famosi vengono compromessi, a volte.

Comunque, se vuoi continuare per la tua strada, ecco qualche idea:
  • Non usare né MD5, né SHA1, ma qualcosa come SHA512. Dai un'occhiata alla libreria mcrypt di PHP.
  • Usa un salt, cioè una stringa casuale che sarà concatenata alla password criptata. In questo modo sarà molto più difficile decriptarla.

Puoi trovare molte informazioni riguardo la sicurezza (e altri importanti aspetti delle applicazioni Web) su hashphp.org.
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
alex hai ragione, pero secondo me il punto debole del sistema non è tanto la criptatura ma la password.
se uno usa come pass "123456" criptata prima in md5 passata per sha1 e ancora sha512 saltata ecc di sopra di sotto davanti e dietro quanto ci mettono a bucarti il sistema?
cioè tu hai una casella di input per inserire la password quindi, non so se è possibile, ma posso simulare l'invio di tale casella, quindi con un bruteforce che mi crei tutte le pass partendo dai carattere o con un "dizionario" è questione di tempo ma il sistema viene bucato.
quindi per la sicurezza non c'è solo la criptatura, ma anche la scelta di una pass solida e forse , come ti ho accennato, anche se non risolutivo (la guerra dei costruttori di casseforti con gli scassinatori è una guerra continua, senza vinti ne vincitori) è interrompere la connessione dopo un certo numero di tentativi errati, anzi non il numero la "velocità" cioe tentativi errati nell'unità di tempo (sto provando un sistema e per ora mi sembra funziare) quando l'ho finito lo posto (se interessa)
 
Ultima modifica:

Malware

Utente Attivo
19 Lug 2012
112
0
0
@alex
Grazie.
Mi sa che vado per la soluzione che usa woltlab cioè sha1 (io useró sha512) saltata.
Poi posto l'algoritmo. Woltlab usa perfino un doppio sha1.
Il salt lo posso fare così?

PHP:
<?php

$time=mktime();
$salt=md5($time);

?>

@borgo
Si, infatti un'esempio di password che ho cominciato ad usare è:
Iphone_cacca.armadio45<56sveglia
Me le scrivo tutte su un foglio eheh:)

Poi saranno i miei utenti ad andare nei guai se usano password tipo 12334567890.
Cavoli loro

Per il tuo script, postalo pure, mi sa che ne faccio uno anche io:)
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
esatto una pass difficile e robusta va più che bene (a parte la successiva codifica).
una piccola osservazione vedo che usi tra i caratteri "<" spero che tu non utilizzi anche ">" perche secondo me, visto che si deve verificare la password formalmente (composta da caratteri ammesi)
qualcuno potrebbe inserire unas pass <script>eccc...</script> e non si sa mai cosa potrebbe succedere.
Poi saranno i miei utenti ad andare nei guai..
non lo so è sempre uno spiraglio aperto sul database. (in una parte del mio sito la pass l'assegno io, non la faccio scegliere)
non posto ancora lo script perche sto ancora valutando quale può essere il "limite" di velocità
 
Ultima modifica:

Malware

Utente Attivo
19 Lug 2012
112
0
0
Io nei siti che VISITO uso il carattere <.....per ora non >
Nel mio browsergame i caratteri < e > come password li permetto: tanto la password non devo mai richiamarla e visualizzarla.
Giusto?

Ecco lo script woltlab che dicevo:

PHP:
<?php

//$salt sarebbe il salt preso dal database
//$passdb è la password salvata nel database
//$passwrited è la password inserita dall'utente

$password1 = sha1($salt.sha1($salt.sha1($passdb)));

$password2 = sha1($salt.sha1($salt.sha1($passwrited)));

if ($password1 == $password2) {
     //blablabla
}else{
     //riprova, sarai più fortunato
}

?>
 

borgo italia

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
4 Feb 2008
16.035
146
63
PR
www.borgo-italia.it
ciao
scusa una cosa, ma la pass la salvi in chiaro?
nel db la salvo codificata, credo che è quello che si debba fare.
se per caso uno riuesce ad accedere si trova tutte le pass
 

Malware

Utente Attivo
19 Lug 2012
112
0
0
No sempre criptata

Vero, posso permettere i tag html non perchè non devo mai visualizzare la password ma perché tanto poi la cripto :dormo:
Attualmente la criptavo con sha1(md5()) ma ora passo al metodo utilizzato da woltlab.

Io alla registrazione farei così:

PHP:
$salt=mktime;
$salt=salt($salt); //creo il salt

$passwrited=$_POST['password']; //recupero la password inserita
$passwrited=sha1(md5($passwrited)); //cripto in sha1 l'md5 della pass inserita

//salvo $salt e $passwrited nel database

Login:

PHP:
$passwrited=$_POST['password']; //recupero la password inserita

$passdb=$blablabla[0] //recupero la password dal db che è la password criptata in md5 e sha1
$salt=$blablabla[1] //recupero il salt dal db


$password1 = sha1($salt.sha1($salt.sha1($passdb)));
$password2 = sha1($salt.sha1($salt.sha1($passwrited)));


if ($password1 == $password2) {
     //blablabla
}else{
     //riprova, sarai più fortunato
}
così dovrebbe essere più sicuro no?