下面是摘自thinkphp官方的一个公告,官方直接贴出这些东西是非常不负责的行为,跟上次apache公开的Struts2的代码执行一样的行为,会造成很多用户被黑。建议类似的厂商不要再做这种蠢事。; z2 X0 c( \* ^- L" ^' w
ThinkPHP 3.1.3及之前的版本存在一个SQL注入漏洞,漏洞存在于ThinkPHP/Lib/Core/Model.class.php 文件4 K. W& l8 p& D% }4 n& @% j
根据官方文档对”防止SQL注入”的方法解释(见http://doc.thinkphp.cn/manual/sql_injection.html)
& x3 k) q1 k/ ?- z0 J1 h: s使用查询条件预处理可以防止SQL注入,没错,当使用如下代码时可以起到效果:6 a/ r B" k% I6 F
$Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
& K3 |2 ~# r6 A, f
0 m! |& M. a: K3 K) e' I 或者4 K/ {; J& l, s4 a" k" B
$Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();7 o0 I" K- c1 U5 x. G3 N
; x2 E- z7 [6 M* L N+ J
但是,当你使用如下代码时,却没有”防止SQL注入”效果(而官方文档却说可以防止SQL注入):
3 k% T$ N3 m1 u6 w: C- H$model->query('select * from user where id=%d and status=%s',$id,$status);
0 l% E" [0 ~2 t8 b
: u$ Q& e0 J+ b9 Z7 K或者
0 c; A, T! V9 Y5 _4 {$model->query('select * from user where id=%d and status=%s',array($id,$status));; U1 K, `) z4 W. [" G' p
" X. g' z+ S" |1 j, Q6 C$ m
原因:
1 s' v9 Q9 d2 e' d. |' P: V. QThinkPHP/Lib/Core/Model.class.php 文件里的parseSql函数没有实现SQL过滤.2 P2 G$ z8 P" A" ~1 h! ^! u3 r7 C$ O
原函数:9 M; I3 X$ x! z$ f
protected function parseSql($sql,$parse) {
3 j& a4 z7 G d' B* Q // 分析表达式
* {5 g. G% \2 C) m. m) w4 U# r if(true === $parse) {5 O. a2 s* y3 p: p9 C: }
$options = $this->_parseOptions();+ d& e0 r! B& f5 \# r
$sql = $this->db->parseSql($sql,$options); _! q h+ q6 G( K
}elseif(is_array($parse)){ // SQL预处理 ~! B2 }' T, Q
$sql = vsprintf($sql,$parse);- G" f1 y7 l3 X) C2 b$ u
}else{
, N5 b: c0 l4 K, ` $sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
- A9 l. ]9 l% K& r }, X6 E' h+ g- U# f4 F$ G* ?
$this->db->setModel($this->name);0 d, f6 O! @! s/ A
return $sql;
7 q+ L: U4 T: a* o4 E }) c: b: P7 s7 p* p2 r% W
6 A- M6 ~0 _6 e @' m- Y% ]
验证漏洞(举例):. }& ?% z4 u) l! D
请求地址:
6 I. A" c9 E1 Uhttp://localhost/Main?id=boo” or 1=”1, j J7 w3 @$ x) G
或
* q2 b* y8 d7 g; w' Q: Jhttp://localhost/Main?id=boo%22%20or%201=%2218 A \: y+ i8 u- z
action代码:% Y) Q$ Q& E9 G2 b d7 c. {+ ?
$model=M('Peipeidui');
8 |6 R3 \, D5 G8 H/ [" ~4 t $m=$model->query('select * from peipeidui where name="%s"',$_GET['id']);
K @& S2 _/ E# c* r1 n+ N dump($m);exit;+ l' w4 k) d# J; Z" k2 ~% V
或者0 j6 B& G/ ^2 ]
$model=M('Peipeidui');# h' M( b3 F- |2 X+ n
$m=$model->query('select * from peipeidui where name="%s"',array($_GET['id']));
* b6 p8 ` d, l4 z1 r6 n- m dump($m);exit;
. F2 ?% @2 y- X1 l结果:0 d6 M7 \6 k! A. `, J
表peipeidui所有数据被列出,SQL注入语句起效.
7 `: w& d" i# \) r$ O) S' `; e解决办法:
2 I6 G4 j9 Q8 a: ?将parseSql函数修改为:6 m$ N+ n) W. K4 a4 u
protected function parseSql($sql,$parse) {4 T% V2 @5 |- L. x2 A
// 分析表达式2 D9 k' V0 D4 H4 B! n; D
if(true === $parse) {
T ^/ y& g) `5 h $options = $this->_parseOptions();
, M; X* P: z+ j) n $sql = $this->db->parseSql($sql,$options);
6 `# d# O. @# m) g }elseif(is_array($parse)){ // SQL预处理
8 E& _( I K4 Y @ { $parse = array_map(array($this->db,'escapeString'),$parse);//此行为新增代码
9 M! j0 b' g9 o8 z. T, W, c) o $sql = vsprintf($sql,$parse);4 A' w5 {. X% e( ?5 b3 a
}else{7 `, v5 l7 T/ S' u
$sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
- J1 u9 ?, z! I! G3 l' D7 G }
2 R" |" D( u! @. C$ D $this->db->setModel($this->name);1 n2 F9 U7 Q7 R' Q! O' Q
return $sql;
9 B( v$ A2 H: b E% t# ]+ o& I! E3 ~ }
; [& G/ I H: b5 s: e3 m
) |- K1 p1 r% V) Y% s$ a/ t总结:4 i: w# e) F0 m5 j4 \( }: z7 z' v/ J5 _1 W: U
不要过分依赖TP的底层SQL过滤,程序员要做好安全检查
& a3 S" T# G2 i2 s3 z$ l. _不建议直接用$_GET,$_POST
3 }% B7 K% x3 o Y[/td][/tr]
- v1 D' g* c( ]7 j. E[/table]+1
3 D9 E- X* J1 D. s& q- K7 N+ b$ L+ D+ k
+ X( n* x5 N/ G4 S( x3 b
|