找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2720|回复: 0
打印 上一主题 下一主题

ThinkPHP框架通杀所有版本的一个SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-7-27 18:30:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑。建议类似的厂商不要再做这种蠢事。" _5 r( q4 O( X7 }  c
ThinkPHP 3.1.3及之前的版本存在一个SQL注入漏洞,漏洞存在于ThinkPHP/Lib/Core/Model.class.php 文件$ p/ B! `# l2 F0 h/ F
根据官方文档对”防止SQL注入”的方法解释(见http://doc.thinkphp.cn/manual/sql_injection.html)1 D4 r% _4 _5 [9 W0 |
使用查询条件预处理可以防止SQL注入,没错,当使用如下代码时可以起到效果:
/ E% w& g2 N# G7 b7 ~$Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();& p+ F0 g! i0 k6 j+ X7 {7 i

# i- I5 q: k( Q; p; s 或者1 \1 l  P9 Z1 d6 q
$Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();& y0 @' K( L: I8 y( Y% _4 b
: `/ L$ ?2 y; u- }2 {$ z/ q: g+ g
但是,当你使用如下代码时,却没有”防止SQL注入”效果(而官方文档却说可以防止SQL注入):
. w8 _/ I! n& o4 p$model->query('select * from user where id=%d and status=%s',$id,$status);8 @/ o6 o+ v3 b

/ c, z5 M5 N5 h8 v2 \3 v或者
/ W7 e2 {# [. y' D* U$model->query('select * from user where id=%d and status=%s',array($id,$status));
: M- n0 f, q% `* o
1 J  z- E* X+ Q' \6 {5 ]+ ? 原因:
; f7 ~8 Y9 F& o, uThinkPHP/Lib/Core/Model.class.php 文件里的parseSql函数没有实现SQL过滤.
1 M, b$ D' b7 N) r; U/ a) A( e原函数:. y, t, m! ?+ ]8 P. N( C
protected function parseSql($sql,$parse) {
, V2 B3 F/ C2 g3 ~. U        // 分析表达式
  i; x- F5 X2 l9 C        if(true === $parse) {
9 I& x. V3 a, N5 J# }            $options =  $this->_parseOptions();
5 D9 |. A4 t( O  G7 N. x! }3 r            $sql  =   $this->db->parseSql($sql,$options);" h3 M  P, `8 b% ~/ E
        }elseif(is_array($parse)){ // SQL预处理% {/ y/ K0 Z% u* x
            $sql  = vsprintf($sql,$parse);
0 I  B4 ?4 k/ r+ V        }else{: r# A" n( J' u- }% z
            $sql    =   strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));. z  M$ _9 c% }- U  n" t
        }
2 C" j* P- n$ n3 w        $this->db->setModel($this->name);1 B+ n- U- C# @# }( H6 K
        return $sql;) f; s4 D% {, ]/ o! o& |; s
    }1 U$ y  }& N: L2 O: I
+ ]3 @8 P$ X3 n, c
验证漏洞(举例):
6 ?. Z8 C$ @" t& I6 ]请求地址:( R0 X; S5 R+ n' E
http://localhost/Main?id=boo” or 1=”17 d  i, g; I0 i; B

4 p" L  G! }9 u/ S4 Mhttp://localhost/Main?id=boo%22%20or%201=%221% x% a4 b$ Z* @7 H
action代码:
7 T3 ?0 {. }5 c. y9 o$model=M('Peipeidui');. K* h  v5 m9 d8 E7 q
        $m=$model->query('select * from peipeidui where name="%s"',$_GET['id']);6 I8 A) j# a- F. n4 `5 k
        dump($m);exit;
% X, Z' i. X3 K( a或者
3 O! X1 d3 t7 O5 f1 C- r4 z  F$model=M('Peipeidui');: b& J1 `* K2 S% U; B# H' \/ C
        $m=$model->query('select * from peipeidui where name="%s"',array($_GET['id']));: [# z, ]* f# }- \
        dump($m);exit;
) ]1 O8 v6 H5 D% ?结果:6 B% \' O- T; n  Q* h1 I: h
表peipeidui所有数据被列出,SQL注入语句起效.8 ^! o  o( v! \
解决办法:4 M! k  C  [1 m0 r. T+ n
将parseSql函数修改为:, ]5 j4 h# x6 U4 _# D
protected function parseSql($sql,$parse) {. m. g: `; ^" f3 ?0 ?
        // 分析表达式
9 r7 H4 u' s4 A8 o6 n        if(true === $parse) {
) V6 k5 J  a" |3 ?4 n            $options =  $this->_parseOptions();7 `$ x) K3 p% v) x
            $sql  =   $this->db->parseSql($sql,$options);
* }8 |& U* K5 d+ ^! ]6 i0 F        }elseif(is_array($parse)){ // SQL预处理
2 T( R. D5 p4 J$ i4 @            $parse = array_map(array($this->db,'escapeString'),$parse);//此行为新增代码
0 g% ~+ h7 N& x: @            $sql  = vsprintf($sql,$parse);
$ h; T! v, G. ^$ O9 y        }else{
% D( M$ s% g* D$ X            $sql    =   strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));1 Z8 F4 _+ j$ k2 ~2 p" _' u
        }
- {& U$ |: m2 ^7 f) P# h  @5 s        $this->db->setModel($this->name);
! {9 u" {' Y- F        return $sql;4 m! |$ E+ f7 F  ^) h- N% U
    }
0 G# }1 ^  S7 G& T8 U1 r, w
% k! ]+ i- b- s3 x总结:
  x# |- K' Y  }% s/ b$ G6 E0 L5 ?: ]不要过分依赖TP的底层SQL过滤,程序员要做好安全检查
9 e3 k  p5 ?. b# X! f0 y# D不建议直接用$_GET,$_POST
# W  d9 H, }- F# [$ V. r[/td][/tr]
) S" f: y% Q2 @) o$ [& Z[/table]+1
; W$ C" t- O4 l
. k; O& W' g; m1 `( W. ?6 a- F0 G- C* F6 L1 s; T4 Y' d$ [
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表