Ho perso qualche vulns qui?

5

Recentemente ho preso un pasticcio in un'intervista di Security Engineer e non ho ricevuto alcun feedback specifico su come ho fatto. Mi piacerebbe ri-chiedere la domanda alla comunità in modo da poter lucidare su questi elementi. La mia lista di vuln trovati sono sotto.

Sei in una pagina di accesso, due elementi del modulo Utente: / Password: il tuo nome utente è Peter.

Dopo aver eseguito correttamente l'accesso all'app, verrai indirizzato a una pagina che dice Hello "Peter". (La fonte di "Peter" in questa pagina proviene dalla variabile utente popolata nel modulo nome utente login)

Il codice generico per questo è il seguente:

public String login( String user, String pass ) { 
       if (pass == DB.lookup(user)){ 
            return "Hello " + user; 
           }
       else { .....} 
       } 
  1. Quali sono tutte le vulnerabilità presenti in questa applicazione di login di esempio?
  2. Come li sistemerai?
  3. Come conserveresti le tue password?
  4. Se li memorizzi in questo modo, con quale meccanismo recuperi la password per convalidarla contro ciò che l'utente ha digitato nella forma della password?

    Ecco ciò che vedo finora:

XSS: il fatto che l'input dell'utente (utente) sia inserito nella pagina jsp di risposta senza passare attraverso una libreria o un validatore di codifica significa che sei di proprietà.

Correzione: implementerei il disinfettante dal progetto del codificatore java OWASP nell'elemento HTML.

Vorrei memorizzare le password come hash salato usando bcrypt. Un valore unico per ogni password con hash.

    
posta Taken Beatings 10.11.2015 - 23:19
fonte

3 risposte

3

Nessuno ha ancora menzionato esplicitamente che esiste il potenziale per l'iniezione SQL. La stringa utente richiede una convalida adeguata per garantire che sia presente e contenga solo un nome utente valido.

    
risposta data 12.11.2015 - 11:39
fonte
3

Senza vedere il codice sul server, non posso essere sicuro al 100%. Soprattutto perché non so che cosa fa DB.lookup() . Per quel che ne so, potrebbe gestire molti di questi problemi di sicurezza.

public String login( String user, String pass ) { 
   if (pass == DB.lookup(user)){ 
        return "Hello " + user; 
       }
   else { .....} 
   } 

What are all of the vulnerabilities present in this sample login application? How would you fix them?

  1. Nessun timeout nel tentativo di accedere tramite IP / cookie e nessuno per utente. Facilmente permette sia un attacco Denial of Service (anche DDoS), e un attacco a forza bruta.
  2. No Verifica se user o pass sono nulli e quindi della lunghezza corretta e nel formato corretto da verificare rispetto al database. Cosa succede se la pagina restituisce un errore e ti permette di provare a capire di più attraverso tentativi ed errori?
  3. Possibile attacco SQL injection su DB.lookup(user) , ma è anche possibile che DB.lookup() lo gestisca.
  4. return "Hello " + user; Di nuovo, perché non c'è un controllo corretto, puoi usare questo per inject qualsiasi nella pagina del server. Ciò significa che potresti eseguire il% canaglia ASP / JSP / PHP / whatever .
  5. Ancora una volta, senza vedere il codice DB.lookup() , non posso dire cosa fa, ma posso fare un'ipotesi. Sembra che tu stia confrontando pass con username. Ciò potrebbe significare che potresti essere in grado di provare ad accedere con la password uguale a quella del nome utente e utilizzarla per accedere senza la password. Potresti accedere con login("Jake", "Jake"); , e funzionerebbe.

How would you store your passwords?

Nel database, non qualsiasi cosa a cui l'utente dovrebbe avere accesso, utilizzando bcrypt / hashed + salted (univoco, ovviamente) + una affidabile SlowEquals() password. Un% diSlowEquals /% co_de correttamente implementato impedirà gli attacchi di temporizzazione del canale laterale.

If you store them that way, by what mechanism do you recover the password to validate it against what the user typed into the password form?

Controlla se l'immissione della password non è nulla, è di lunghezza adeguata per una password e non contiene caratteri non prenotabili. Massimo tre tentativi Controlla se l'hash salato corrisponde alla password.

Per quanto riguarda sia XOR che user , è necessario verificare se non sono nulli, che hanno la lunghezza appropriata per ciascun campo nel database e che sono nel formato corretto. Per verificare il formato corretto, puoi usare regex per assicurarti che sia alfanumerico con i simboli corretti. Oppure puoi rimuovere tutti i caratteri non utilizzati.

E non dimenticare, devi testare sia il nome utente che la password contro pass Altrimenti puoi accedere con il nome utente dell'utente come password! Orribile!

Il codice più sicuro potrebbe essere simile a questo (pseudo codice non verificato, btw) :

Pseudo classe per DB:

public static class DB
{
     public static boolean lookup(string u, string p)
     {
          // Test salted hash against the user's hash for that particular username.
          return (encryption.testPassword(p, getUsersHashedPassWord(u))) ? true : false;
     }
}

Lo pseudo-codice di controllo degli errori:

private boolean properLength(String u, String p)
{
     return ((u.length > 3 && u.length <= 12) && (p.length > 8 && p.length <= 30)) ? true : false;
}

private boolean properFormat(String u, String p)
{
    return (regex.Valid(u, usernameRegex) && regex.Valid(p, passwordRegex)) ? true : false; 
}

private String stripBadStuff(String stuff)
{
    // Just in case or something...
    return EncodingFunction.ToASCII(stuff).regexReplace(badCharacaterRegex, ""); 
}



public String login( String user, String pass ) 
{ 
   if (!loginTriesExceeded) // Currently unhandled for example.
   {
       if ((user != null && pass != null) && properLength(user, pass) && properFormat(user, pass))
       {
            // Unhandled for example. This is so they can't change their IP address to continue trying.
            if (!userLoginTriesExceeded)
            {
               String newUser = stripBadStuff(user);
               String newPass = stripBadStuff(pass);
               // Would be changing DB.lookup() to return true if valid login is detected. DB.lookup(newUser,newPass) will now be assumed that it tests the plaintext password against the salted hash. 
               if (DB.lookup(newUser, newPass)) 
               { 
                    // Prevent injection. This will assume DB.lookup() tests the password against the stored hash.
                    return "Hello " + newUser; 
               }
               else 
               {
                    return "Invalid login.";
               }
           }
           else
           {
                return "User login attempts exceeded.";
           }
        }
        else
        {
             return "Invalid login";
        }
    }
    else
    {
        // Do nothing, or inform the user that they've exceeded max logins.
        return null; // So all code paths return a value. 
    }
} 

Ricorda che è uno pseudo codice non verificato. Potrebbero esserci alcune cose che mi sono perse.

    
risposta data 12.11.2015 - 15:10
fonte
0

Vulnerabilità che riesco a vedere:

  1. Qui potrebbe non essere considerato una vulnerabilità (come tale), ma la password non sembra essere sottoposta a hash in quel codice.
  2. Il confronto tra stringhe usando == è vulnerabile all'analisi statistica dei tempi.
  3. L'XSS che hai trovato.
  4. Suppongo che DB.lookup sia sicuro da usare in questo modo senza ottenere vulnerabilità di SQL injection. Manca ancora la gestione degli errori, come sottolineato da @SourLolita.
  5. Non sembra esserci alcuna protezione XSRF, non è visibile almeno in quel codice. Non so come sfruttarlo in questo caso.

Come risolverli:

  1. Hash password utilizzando un algoritmo di hashing della password, come bcrypt o scrypt.
  2. Utilizza la funzione di confronto / controllo della libreria di hashing delle password.
  3. Passa il nome attraverso una funzione di escape appropriata, eventualmente fornita dal framework in uso.
  4. Aggiungi un controllo degli errori. Se i nomi degli utenti sono segreti, l'immunità ai tempi si applica anche qui, e quindi sarà complicata.
  5. Dovrei leggere su questo. È passato un po 'di tempo. Un modo è quello di avere un token casuale speciale inviato con il modulo e come cookie e richiedere che corrispondano.
risposta data 12.11.2015 - 12:17
fonte

Leggi altre domande sui tag