你的 CakePHP 应用安全吗?
最近在写 CakePHP 网站的时候,发现一个 Cake 开发人员经常犯的错误,这个错误实际上会成为网站安全漏洞,使得网站很容易被攻击。
先来看如下代码,这是一个用户注册的 action,通常的写法是:
<?php
class UsersController extends AppController {
//….
function register()
{
if (!empty($this->data)) {
$this->User->create();
if ($this->User->save()) {
$this->redirect(array(’action’=>’index’), null, true);
} else {
$this->Session->setFlash(__(’Failed to register. Please, try again.’));
}
}
}
//….
}
?>
看起来这个代码片断很简单,很寻常,所以也很流行。但这个流行却让很多开发人员忽略了安全性问题。实际上我们并没有对表单提交过来的数据进行过滤,也就是说你可以通过客户端,给 $this->data 加入各种字段,只要这些字段名和数据表中的能够对上,都会被保存进数据库中。最致命的字段是什么?我们都知道,Cake 的表设计通常都有一个 ‘id’ 字段,这也是为了方便快速编程而设计的默认表关键字。这个 id 就是最致命的字段。测试的方式很简单,通常我们可以通过 url 或者其它方式知道某个用户的 id,那么在注册的时候,使用 Firebug 编辑 HTML 表单,加入一个输入 id 的文本框:
<input type=”text” name=”data[User][id]” />
然后你就可以在表单中填入一个已存在的用户 id,如果你不知道任何用户的 id,那么可以试一下 1,通常前几个用户都是网站的相关人员的帐号,也极有可能拥有比普通用户更多的权限。其它注册项仍然照常填写,完成之后提交。接下来会发生什么呢?register() 方法把你的信息写入数据库了,但并不是创建一个新的用户,而是覆盖了你所填写的用户 id 所对应的那个用户,实际上你已经可以修改到那个用户的密码了。
想要修复这个问题,必须对 $this->data 进行过滤,至少要 unset($this->data[’User’][’id’]); ,最保险的是把你真正需要的数据保存在一个数组里边,然后传给 $this->User->save(),如:
<?php
//….
if (!empty($this->data)) {
$this->User->create();
$data = array(
’username’ => $this->data[’User’][’username’],
’password’ => $this->data[’User’][’password’],
//….
);
if ($this->User->save($data)) {
$this->redirect(array(’action’=>’index’), null, true);
} else {
$this->Session->setFlash(__(’Failed to register. Please, try again.’));
}
}
//….
?>
安全问题是最为重要的,不管你用什么框架,不管它有多方便,你都要去关注这方面的问题,不要被表面的“快速开发”所麻痹。