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?
- 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.
- 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?
- Possibile attacco SQL injection su
DB.lookup(user)
, ma è anche possibile che DB.lookup()
lo gestisca.
-
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
.
- 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.