• User Newbie

    Sicurezza applicazione web

    Salve a tutti, dovendo gestire la sezione riservata di alcuni siti (e ovviamente anche l'output dei valori passati tramite querystring nella zona pubblica) volevo discutere, se fosse possibile delle tecniche utilizzate da me e da per capire come migliorarci reciprocamente per rendere le nostre applicazioni web davvero sicure.

    Login
    Si tratta della parte in cui controllo che l'utente sia loggato sul sito o meno.
    Nel caso l'utente non sia loggato, nella pagina index.php compare il form di login, nel caso di pagine interne compare un messaggio di errore che invita ad un login rimandando alla index.
    codice PHP:

    
    if($varUtente==$auth) 
        include 'main.php'; 
    else 
        include 'login.php'; 
        (oppure, se non è la index) 
        include 'error.php';
    
    

    A questo punto la domanda è relativa alle due variabili utilizzate:
    $auth è una stringa random unica per tutto il sito che funge da "controllore", è definita in un file php del sito e non può essere modificata direttamente.
    $varUtente è invece una stringa che è salvata in fase di login. Seguendo questa guida (php.html.it/articoli/leggi/875/sessioni-alternative-in-php/) su un altro sito ho infatti evitato di usare sessioni e/o cookie per l'applicazione, ma la logica è questa:

    1. Inserisco nick e password
    2. I dati vengono confrontati nel database con quelli esistenti (dopo essere passati al vaglio delle funzioni di sicurezza, ne parlo più avanti)
    3. Se il login va a buon fine viene generato un token della durata di 30 minuti (inviato alle pagina successive tramite querystring) il cui valore è salvato nel database insieme alla sua scadenza e ad alcune variabili di controllo (id utente, nickname, livello e variabile $auth in modo da non cercare più dati nella tabella degli utenti).
    4. Nelle pagine successive recupero il token, controllo che esista nel database, estraggo la variabile utilizzata come "controllo" (che sarebbe quella random usata nel sito), la salvo in $varUtente e controllo che le due coincidano per dare i permessi in entrata.

    Vi chiederete perchè faccio così e non imposto una variabile a true se la sessione esiste e non è scaduta: perchè impostando una singola variabile a true e avere quindi qualcosa del tipo

    
    If(sessione_esistente) $var = true
    
    if($var=='true') echo "sei loggato!";
    else "non sei loggato";
    
    ``` Avevo il timore di scordarmi di dichiarare di base la variabile a false e, nel caso il register_globals fosse settato male, passando tramite querystring un "pagina.php?var=true" un malintenzionato avrebbe avuto l'accesso comunque.
    Così le variabili diventano due di cui una sicuramente settata e mi sento più sicuro.
    
    **Hash della password** 
    Non ho la necessità di recuperarla, quando serve preferisco spedire una  mail per fare in modo che ne venga generata una casuale che l'utente  cambierà.
    codice PHP:
    

    function criptpass ( $pass )
    {
    $passaggio = md5($pass);
    $password_hash = sha1($passaggio.$auth);
    return $password_hash;
    }

    
    **Eliminazione vulnerabilità XSS e HTML** 
    Mi duole dirlo ma qui non ho fatto passi da gigante e sono più o meno  rimasto al livello dell'altro post. Più che altro per due motivi:
    1) Non mi è ancora capitato di usare un editor HTML semplificato. Nel  caso l'idea suggeritami era di "eliminare la possibilità di inserire  attributi", ma anche questo non è fattibile immediatamente: se dovessi  usare un editor nel quale mi è richiesto di usarli (penso ai vari editor  come fckeditor o altri che vedo nei CMS)
    2) Dato che questa parte è quella che utilizzo anche per filtrare le  variabili recuperate tramite GET e POST ho due problemi che tutt'ora  devo trovare il tempo di sviluppare:
    - Nel caso di array passati tramite GET esiste una funzione (senza  riscoprire l'acqua calda) che in maniera ricorsiva mi pulisca tutto  (meglio ancora: esiste una funzione che in maniera ricorsiva mi pulisca  tutto il mio GET e/o POST?)
    - Se al posto di quanto uso adesso (che trovate sotto) usassi qualcosa tipo
    trim(addslashes(htmlentities($var))) non otterrei lo stesso risultato in termini di sicurezza?
    Io di base faccio così:
    
    codice PHP: 
    

    function killHTML($html)
    {
    $myReg = '/<[^>]?[^>]?>/';
    if(preg_match($myReg, $html))
    {
    $var = preg_replace($myReg, '', $html);
    }
    else
    {
    $var = $html;
    }
    $badHTML = array("<", ">", "//", "/>");
    $var = str_replace($badHTML, '_', $var);
    return $var;
    }

    function killXSS($var)
    {
    $badString = array('<javascript', '<script', '</script', '<iframe', 'onload = ', '<layer', '<meta http', '<object', '</object>', '<input', 'background = ', '<bgsound', '<style', 'http');
    $goodString = array('jav-asc-rip-t', '', '', 'fr-a-me', 'onl-oad', 'la-y-er', '', '', '', '', '', '', '', 'ht_tp');
    $var = str_replace($badString, $goodString, $var);
    foreach($badString as $badWord)
    {
    if(stristr($var, $badWord))
    {
    $var = str_replace($badString, $goodString, strtolower($var));
    }
    }
    return $var;
    }

    function killALL($var)
    {
    $var = killXSS($var);
    $var = killHTML($var);
    $var = addslashes($var);
    $var = str_replace(chr(13), "<br />", $var);

    return $var; 
    

    }

      
     
    **Gestione** 
    Per gestione intendo il recupero di valori da form e di valori tramite querystring (GET e POST).
    Utilizzando le funzioni sopra descritte faccio un semplice $var = (killALL($_GET['valore'])) per eliminare XSS e HTML.
     
    **Domande**
    **1)** Domanda personale di cui leggevo questi giorni: è utile in fase di login (quindi quando si devono ricevere  nick e password) controllare che la richiesta arrivi effettivamente da  una pagina nel nostro server o è pura formalità nel caso di pagina ben  studiata e "messa in sicurezza"?
    E nel caso, è utile estendere la cosa a tutte le pagine e quindi imporre  che la pagina precedente (tranne che per la index) sia una pagina sul  nostro server?
    
    **2) **è utile impostare un massimo numero di tentativi per singolo IP (immagino che dopo 3-5 tentativi sia un malintenzionato che tenta di entrare)
    
    Un grazie a chi vorrà discutere di questo spinoso argomento per migliorarci a vicenda :ciauz:.
    Spero che il codice condiviso serva a voi e che vogliate condividere le vostre esperienze per il bene di tutti!

  • User Attivo

    Ho alcuni siti, di cui qualcuno in particolare riceve molte visite e di conseguenza è quello che si becca i + cattivi. Ti dico subito che la maggior parte dei problemi sono esclusivamente su codice di cui si conoscono i sorgenti. Un paio di volte mi è successo che qualcuno appendese al mio PHP del codice malevole, non da javascript o cs del genere ma mi sono ritrovato 2 o 3 righe scritte nei mieo files PHP,ma questo presumo sia da attribuirsi ad altro, forse semplci chmod alterati, ma da chi poi?.
    Di conseguenza conoscendo anche il codice di PHP, Apache e MYSQL
    tutto puo succedere. Ma difficilmente, anche quello che ce scritto nell'articolo da te proposto, che spiega che il file delle sessioni e visibile a tutti gli script PHP con tutte le conseguenze del caso, sia fi facile fattibilita' anche conoscendo il codice.


  • User Newbie

    Quindi diciamo che unendo:

    1. Codice non visibile a tutti
    2. Non utilizzo di sessioni e cookie
    3. Controllo dati input / output
    4. Riconoscimento tramite token

    Potrei già ritenermi soddisfatto secondo te? Ci sono però questioni che per forza di cose riescono a superare queste precauzioni: penso ad esempio ad array passati tramite quesrystring o bachi dovuto al riconoscimento di nick e password...
    Non c'è modo per migliorarsi ulteriormente?


  • User Attivo

    Diamo per scontanto il fatto che il tuo sito non rilasci ed accetti dati da codice malevolo etc etc, ma puo succedere, una volta mi scollegai da internet con altri 2 utenti ed io ero e sn il solo utilizzatore, qualcuno puo leggere lo scambio di dati tra il tuo sito e l'utente.
    Bhe in questo caso non puoi farci nulla se non utilizzare una comunicazione protetta come l'https.
    Cmq a mio modo di vedere le cose del codice non leggibile restringe di molto eventuali attacchi.