Sto studiando infosec, iniziando a farmi strada attraverso alcuni dei giochi di guerra online là fuori. Recentemente abbiamo lavorato su Natas di OverTheWire ( link ) ed è stato molto divertente finora. La mia domanda è legata a una delle sfide del gioco.
** SPOILERS PER IL SEGUITO DEL GIOCO **
Su uno dei livelli, mi viene dato il mio primo incontro con mysql. Il codice di backend appare come questo (il gioco ti permette di vedere il codice php per ogni funzione, almeno all'inizio):
<?
if(array_key_exists("username", $_REQUEST)) {
$link = mysql_connect('localhost', 'natas14', '<censored>');
mysql_select_db('natas14', $link);
$query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\"";
if(array_key_exists("debug", $_GET)) {
echo "Executing query: $query<br>";
}
if(mysql_num_rows(mysql_query($query, $link)) > 0) {
echo "Successful login! The password for natas15 is <censored><br>";
} else {
echo "Access denied!<br>";
}
mysql_close($link);
} else {
?>
<form action="index.php" method="POST">
Username: <input name="username"><br>
Password: <input name="password"><br>
<input type="submit" value="Login" />
</form>
<? } ?>
Ho iniziato a cercare in SQL injection e ho provato alcune cose di base come foo OR 1=1
come input, ma non ho ottenuto nulla. Ho guardato il codice e ho provato a inserire citazioni con il mio input, il che mi avrebbe causato errori quando avevo un numero dispari di citazioni nell'input, ma non sapevo dove andare da lì.
Alla fine ho iniziato a lavorare sulla pagina di OWASP per il test di SQL injection e durante il test dei loro esempi mi sono imbattuto in qualcosa che diceva di provare:
$username = 1' or '1' = '1
$password = 1' or '1' = '1
Questo non ha funzionato, ma per qualche ragione, la mia intuizione ha detto di cambiare il primo '
in "
nell'input $ username e l'ultimo '
in "
nell'input $ password. Così è diventato
$username = 1" or '1' = '1
$password = 1' or '1' = "1'
E ... ha funzionato. soddisfatto la condizione per questo blocco
if(mysql_num_rows(mysql_query($query, $link)) > 0) {
echo "Successful login! The password for natas15 is <censored><br>";
} else {
echo "Access denied!<br>";
}
e mi ha dato la password per il livello successivo.
La mia domanda è ... PERCHE '? Non ne so abbastanza di SQL injection, perché ovviamente sono un noob, ma non capisco esattamente cosa stia succedendo sul server SQL con quel particolare input.
Per reiterare, la query appare come questa (ho usato la funzione di debug nel codice sopra per farla stampare la query):
Executing query: SELECT * from users where username="1" or '1' = '1" and password="1' or '1' = "1"'
Qual è il comportamento di questa query, e in che modo sql la valuta per darmi un risultato TRUE su entrambi gli input (almeno presumo che sia ciò che sta facendo ...)? Ogni volta che cambio il "
in '
in qualsiasi altra configurazione all'interno della query, fallisce. E il fatto che ci sia un numero dispari di "
e '
all'interno della query mi sta facendo impazzire.
Qualsiasi consiglio o spiegazione sarebbe molto apprezzato. Mi sento come se non avrei davvero superato questo livello fino a quando non capisco cosa sta succedendo!