ThinkPHP 3.1中的SQL注入漏洞分析----论ThinkPHP 3.1中的半吊子的PDO封装
我总结ThinkPHP的PDO封装可以用买椟还珠来下结论,表面上封装了PDO支持,但实际却并没有使用到PDO的精髓部分,这不是买椟还珠是什么呢?
花了一些时间了解到ThinkPHP 3.1框架,其官方网站上对其描述得相当不错,但随着我阅读其代码,事实并不是想象的那么好,特别是PDO封装这一部分,处理得相当糟糕,远不如使用原生态的PDO安全, 只是简单地使用addslashes处理用户提交的数据,并没有使用到PDO的精髓部分:prepare预处理和参数化查询。这样其实带来的SQL注入的风险更大,建议对安全性要求较高的环境,不要使用addslashes处理用户提交的内容,如有可能不要使用ThinkPHP框架了,请使用PDO参数化查询从根本上杜绝SQL注入,或使用安全性处理更好的Yii 框架。
首先,分析为何addslashes会在特定条件下造成注入漏洞
请阅读以下几个文章,可得知为何变量使用addslashes处理后仍然造成SQL注入,
PHP字符编码绕过漏洞--addslashes、mysql_real_escape漏洞
http://blog.csdn.net/zhuizhuziwo/article/details/8525789
addslashes:会导致SQL注入漏洞
http://blog.csdn.net/felio/article/details/1226569
可以说,从这点上来看,ThinkPHP框架自吹的水分很多,远不如想象的那么好。另外 PHPCMS v9网上暴露的SQL注入漏洞超多,也是因为其依赖addslashes防止SQL注入(结果证明漏洞更多)。
另外,为了从根本上防止SQL注入,PHP手册上给出的说明:
Prepared statements and stored procedures
Many of the more mature databases support the concept of prepared statements.
What are they? They can be thought of as a kind of compiled template for the SQL
that an application wants to run, that can be customized using variable parameters.
Prepared statements offer two major benefits:
The query only needs to be parsed (or prepared) once, but can be executed multiple times
with the same or different parameters. When the query is prepared, the database will analyze,
compile and optimize its plan for executing the query. For complex queries this process can
take up enough time that it will noticeably slow down an application if there is a need to
repeat the same query many times with different parameters. By using a prepared statement
the application avoids repeating the analyze/compile/optimize cycle.
This means that prepared statements use fewer resources and thus run faster.
The parameters to prepared statements don't need to be quoted; the driver automatically handles this.
If an application exclusively uses prepared statements,
the developer can be sure that no SQL injection will occur
(however, if other portions of the query are being built up with unescaped input, SQL injection is
still possible).
Prepared statements are so useful that they are the only feature that PDO will emulate for
drivers that don't support them. This ensures that an application will be able to use
the same data access paradigm regardless of the capabilities of the database.
也就是说,PHP官方强烈推荐使用PDO的prepare机制,使用参数化查询,即SQL查询模板与变量分离提交,使用bindValue, bindParam的方式处理用户提交数据,一方面可提升性能,另一方面可从根本上杜绝SQL注入问题。
但很可惜的是 ThinkPHP仍然使用addslashes方式处理变量,可见其处理方法极其陈旧,充满SQL注入的风险。
事实上,这套框架在此方面处理的相当糟糕。
让我们追踪ThinkPHP代码,找到其处理数据的方式
Model::save($data='',$options=array())方法用于保存数据,实际上调用了 $this->db->update($data,$options)
再观察DbPdo::update()方法,由Db类继承而来,关键点是:$this->parseSet($data)
protected function parseSet($data) {
foreach ($data as $key=>$val){
$value = $this->parseValue($val);
if(is_scalar($value)) // 过滤非标量数据
$set[] = $this->parseKey($key).'='.$value;
}
return ' SET '.implode(',',$set);
}
parseValue方法中,关键点是escapeString, DbPdo的方法中:
public function escapeString($str) {
switch($this->dbType) {
case 'PGSQL':
case 'MSSQL':
case 'SQLSRV':
case 'MYSQL':
return addslashes($str);
case 'IBASE':
case 'SQLITE':
case 'ORACLE':
case 'OCI':
return str_ireplace("'", "''", $str);
}
}
即简单地使用addslashes处理输入变量。
我觉得ThinkPHP中虽然提供了PDO的支持,但实际上还是使用了addslashes方式处理变量,丝毫没有使用到PDO的精髓部分, prepare预处理SQL, bindValue, bindParam绑定输入变量。
我认为这只是自欺欺人的做法,表面上声称支持PDO,但完全是金玉其外,败絮其中。 可以哄骗一些小白程序员而已,并不到达到其标称的安全性目标。
如果您使用了ThinkPHP框架,我只能认为你相当的不幸,并默默为你祈祷你的站点没有受到SQL注入攻击了。
那么,如何处理这个问题却是留给我们的重大问题,如果你的项目使用了ThinkPHP,这时候修改框架或是换框架是相当不现实的,那么只能从扩展ThinkPHP的数据库访问层类入手,对其进行处理了。
处理办法如下:
重写ThinkPHP的数据库访问层
1. 在项目目录 lib中新建立文件DbPdoMysql.class.php, 在其中定义DbPdoMysql类,并实际crud的四大方法, 如:
class DbPdoMysql extends DbPdo {
public function delete($sql, array $params = array() ) {
}
public function update(array $data, array $options=array(), array $params=array()){
}
public function insert($data,$options=array(),$replace=false, array $params=array() ) {
}
public function select($options=array(), array $params=array() ) {
}
}
然后,具体使用PDO作参数化查询的处理,请查阅PHP手册和ThinkPHP框架的数据库处理流程。
然后,再建立新类,继承自Moble,并重写其四大CRUD处理,大致如下:
class DbPdoMysql extends DbPdo {
public function delete($conditions='', array $params = array() ) {
}
public function update(array $data, $conditions='', array $params=array()){
}
public function insert(array $data,$options=array(),$replace=false) {
}
public function select($options=array(), array $params=array() ) {
}
}
然后,我们在使用模型进行数据库操作时,需要特殊处理一下,不能使用旧的方式处理数据库,以免造成更严重的SQL注入问题。
查询数据时:
$model -> select('where id = ? And name =?', array($_GET['id'], $_GET['name']) )
删除数据时:
$model->delete('where id = ?', array($_GET['id']))
插入数据时使用以前代码即可(DbPdoMysql类中应该完成参数化处理)
强烈建议您根据本文提供的思路,对使用ThinkPHP的项目进行安全处理,以免造成潜在的安全隐患。
另外,关于PDO的防注入原理分析及使用注意事项,请参阅我的文章
PDO防注入原理分析以及使用PDO的注意事项
http://zhangxugg-163-com.iteye.com/blog/1835721
若有异议,请联系笔者信箱 zhangxugg@163.com, 欢迎探讨交流。
相关推荐
在ThinkPHP3.1中,可能存在使用了这些已废弃函数的情况,例如`ereg`系列正则函数、`create_function`等,需要替换为`preg`系列和`Closure`。 1. **废弃函数替换**:PHP7中移除了`ereg`系列的正则函数,如`ereg()`、...
ThinkPHP3.1完全开发API ThinkPHP3.1完全开发文档
8. **安全防护**:包括SQL注入防护、XSS攻击防护等,保障了应用程序的安全性。 9. **插件系统**:通过插件机制,开发者可以快速扩展框架功能,实现个性化需求。 10. **命令行工具**:提供命令行接口(CLI)工具,...
《ThinkPHP3.1新手入门》是一份专为初学者设计的教程,旨在帮助开发者快速掌握ThinkPHP3.1框架的基础知识和应用技巧。ThinkPHP3.1是ThinkPHP框架的一个较早版本,但它的核心理念和基础结构对于理解整个ThinkPHP系列...
用于学习thinkphp3.1开发,适合初学thinkphp的程序员学习使用
最后,手册会讨论ThinkPHP3.1的安全特性,如防止SQL注入、XSS攻击,以及如何设置安全的配置,确保应用程序的安全运行。 通过《ThinkPHP3.1完全开放手册》的学习,开发者不仅可以熟练运用ThinkPHP3.1框架进行Web应用...
《ThinkPHP3.1 完全开发手册20121211.CHM》是一部详尽阐述ThinkPHP3.1框架的参考资料,为开发者提供了全面的指导和深入的解析。该手册涵盖了从基础概念到高级特性的全方位内容,旨在帮助用户快速掌握ThinkPHP3.1框架...
此外,了解thinkPHP中验证码的自定义配置也很重要。`Image::buildImageVerify()`方法接受两个参数,第一个参数是配置数组,用于设置验证码的样式,如长度、字体、颜色等;第二个参数是保存验证码的session名称。例如...
《ThinkPHP 3.1手册20121205》是针对ThinkPHP框架的3.1版本的一份详细开发指南。这份手册包含了该框架的核心概念、使用方法以及最佳实践,旨在帮助开发者高效地利用ThinkPHP进行Web应用的开发。 ThinkPHP是一个流行...
ThinkPHP3.1系列教程
路由是ThinkPHP中实现URL到控制器方法映射的关键。学习如何定义路由规则,实现自定义URL结构,可以提升应用的用户体验和SEO友好性。 4. **数据库操作** ThinkPHP提供了丰富的数据库操作类库,包括连接数据库、...
《ThinkPHP3.1新手入门教程》是一份针对初学者的详尽指南,旨在帮助开发者快速掌握ThinkPHP3.1框架的基本用法和核心概念。这个压缩包包含了一个名为"The Getting Started ThinkPHP3.1 look.chm"的帮助文档,这通常是...
在ThinkPHP3.1版本中,框架进一步优化了设计模式,强化了MVC(Model-View-Controller)架构,提高了开发效率和代码的可维护性。以下是一些主要的知识点: 1. **安装与配置**:手册首先介绍了如何下载并安装ThinkPHP...
基于新浪SAE开发的thinkphp3.1框架
是一个中文版的ThinkPHP3.1.chm完全开发手册,知识点从入门一直讲解到杂项,包含了ThinkPHP全部知识点,容易上手
本文将深入探讨ThinkPHP3.1框架中的RBAC实现,以及如何通过RBAC来管理项目、模块和方法。 一、RBAC概念解析 RBAC是一种权限模型,它将权限与角色关联,用户通过扮演不同的角色获取相应的权限。在RBAC模型中,通常...
14. 安全性:ThinkPHP 3.1 强调安全性,包括防止SQL注入、XSS攻击等,还提供了如Session和Cookie的安全管理。 通过ThinkPHP 3.1 API,开发者可以深入理解这些功能的使用方法,快速上手并高效地开发Web应用。无论是...
ThinkPHP 3.1重视应用的安全性,内置了防止SQL注入、XSS攻击等安全防护机制。同时,对输入数据进行了严格的过滤和校验,有效降低了安全风险。 八、插件和钩子系统 3.1版本引入了钩子(Hook)和行为(Behavior)...