中国网络渗透测试联盟
标题:
ThinkPHP框架通杀所有版本的一个SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-7-27 18:30
标题:
ThinkPHP框架通杀所有版本的一个SQL注入漏洞
下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑。建议类似的厂商不要再做这种蠢事。
! D8 m1 W( b9 S9 a
ThinkPHP 3.1.3及之前的版本存在一个
SQL注入
漏洞,漏洞存在于ThinkPHP/Lib/Core/Model.class.php 文件
5 H- N9 A$ b: ]! ^8 |- _
根据官方文档对”防止
SQL注入
”的方法解释(见
http://doc.thinkphp.cn/manual/sql_injection.html
)
; I# N) A0 @8 ^
使用查询条件预处理可以防止
SQL注入
,没错,当使用如下代码时可以起到效果:
! r0 a, |; F9 {$ K1 a7 H
$Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
: I T& m# \! C! ]6 i) _+ C* p
& P& y$ e4 A$ s( b
或者
0 k4 V& M: y+ i. g; Z \
$Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();
& S' c* U4 K1 _4 k9 j3 K# o
( B9 `/ H5 U% a c
但是,当你使用如下代码时,却没有”防止
SQL注入
”效果(而官方文档却说可以防止
SQL注入
):
8 G' `: B* U/ Y: b' Q+ H- A
$model->query('select * from user where id=%d and status=%s',$id,$status);
1 S V1 S* ^' [/ Z; y
, l1 w/ F* j4 N6 Q! p2 \' J, w$ u% c
或者
3 s& q! t W g8 L* [
$model->query('select * from user where id=%d and status=%s',array($id,$status));
% b S2 e _) E d* r9 ]! C8 B+ N
5 p8 N# l, J3 l. O! Z# Q. G
原因:
+ k' g8 \& {7 [! J7 f
ThinkPHP/Lib/Core/Model.class.php 文件里的parseSql函数没有实现SQL过滤.
/ w7 G5 C1 l; t+ c R4 o$ ]
原函数:
7 Z6 j9 [% y: b8 ]+ g( I3 y+ j
protected function parseSql($sql,$parse) {
6 |; M; l S _1 i' @' t
// 分析表达式
) o' c- @5 O0 n2 a- O8 I
if(true === $parse) {
9 r' z& K3 \7 K5 K/ ^3 s
$options = $this->_parseOptions();
" q5 ]7 n! r! D+ {. u! T/ C
$sql = $this->db->parseSql($sql,$options);
3 R$ j' z0 G/ q+ L# H3 M5 [) Q& k) ~
}elseif(is_array($parse)){ // SQL预处理
6 @! }! \7 d# v
$sql = vsprintf($sql,$parse);
+ x7 S8 E k1 k% c, n: w! f3 r! ~
}else{
6 Z# n; j# b. M& M
$sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
0 @5 ]6 d, \& f% s* `
}
5 y. Q1 Q, u. R2 D: f! ^# }2 ^1 I' N) r
$this->db->setModel($this->name);
: ]' M( n6 r5 m4 W- X' H' @* L2 k
return $sql;
; v# `% Y- P( Q# H8 z4 S4 m, ?
}
9 u2 z/ b& |9 c- p
4 z2 C) J. s/ t1 a* l
验证漏洞(举例):
. A2 W( l8 R. Y% ?
请求地址:
: U4 i* q0 B% A2 r# k
http://localhost/Main?id=boo” or 1=”1
/ h- N, R7 p# F9 A
或
1 I# m" r. F: \" ]5 q: y8 T1 o
http://localhost/Main?id=boo%22%20or%201=%221
( E9 h; e1 L: z8 D7 \
action代码:
+ k: q6 t6 e% v3 P& u' ~
$model=M('Peipeidui');
! t& ]& w9 e( s4 u2 F+ w5 e
$m=$model->query('select * from peipeidui where name="%s"',$_GET['id']);
( Z) [1 w3 ^+ t5 _; m% s5 |
dump($m);exit;
3 B+ H( B& x" \" D& x
或者
! }) \* X, A/ z r/ _. e- w8 E
$model=M('Peipeidui');
. [' I [4 G" z" a% N# i
$m=$model->query('select * from peipeidui where name="%s"',array($_GET['id']));
; Z' H! z" F5 m/ _& {# y
dump($m);exit;
4 ?$ D1 M, X0 M( C/ U) G) i, S. Q
结果:
" x1 B3 L! s& \* H, a4 L+ d) @, y6 b( ]
表peipeidui所有数据被列出,
SQL注入
语句起效.
: F, F& n; J+ U% g, { v3 t# ~
解决办法:
6 ~+ F% p+ m$ r: G$ W/ C' ]
将parseSql函数修改为:
( P; c& S4 |4 X% J2 F2 z- |8 a3 d
protected function parseSql($sql,$parse) {
6 ^% b9 r$ N4 y% j
// 分析表达式
+ a5 P* b5 O J( j4 F4 O
if(true === $parse) {
) I q9 x6 d. o9 y& h; n" U7 g
$options = $this->_parseOptions();
: n0 }3 G7 |9 j- k2 K5 O8 ^
$sql = $this->db->parseSql($sql,$options);
# O! j# p, |( S. b
}elseif(is_array($parse)){ // SQL预处理
$ t" z/ O# m4 W9 U; i. R+ [. U# y
$parse = array_map(array($this->db,'escapeString'),$parse);//此行为新增代码
2 u, c% ~) m9 s) B6 |8 \
$sql = vsprintf($sql,$parse);
1 V6 r2 @' g8 ]% Y$ z
}else{
6 s" [- G) I- s$ D' y. ^
$sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
6 O3 U9 X- l3 T$ q! L9 N# ?1 L' c
}
% k: B4 E$ ^' A6 E( d5 ?
$this->db->setModel($this->name);
w0 |2 r9 t2 o& c$ `
return $sql;
( f* i' I( r1 ^' z
}
" }0 n6 s" |" T5 G, z
9 P; O$ ^! `2 z% [) ]6 K
总结:
% Z! W. a7 C7 n: a. H
不要过分依赖TP的底层SQL过滤,程序员要做好安全检查
+ W9 I& O5 s$ d% h2 k. Z
不建议直接用$_GET,$_POST
: h0 Y, G* J( n( v4 ?7 `. V% l
[/td][/tr]
$ S) T. W, C% k, z4 j( e. T: _5 U
[/table]+1
- K+ e8 x7 j( j2 G/ M5 f3 Y
; Z8 p5 v1 O- T( S
. [/ G4 z$ s5 I! ^3 Y. I3 N
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2