thinkphp 需要注意的一些漏洞(可能已经修复,此处仅是学习)

本文分析了ThinkPHP框架在处理SQL注入方面的不足,指出了其依赖的传统转义函数存在的安全问题,并建议使用PDO的预处理机制来提高安全性。
部分内容摘自网络。看完之后受益匪浅,和大家分享
之前发过关于thinkphp的一个ip获取漏洞,官方木有反应
http://www.thinkphp.cn/bug/2756.html
于是就考虑到官方的关于web中的sql注入过滤的问题是否也是非常马虎。
看来几篇文章,发现确实这个thinkphp 框架写的不怎么样。对于安全问题视而不见。以下部分内容摘自网络以及本人测试
测试:下载thinkphp的当前最新版本ThinkPHP_3.2,我们来看看代码,用事实说话,在sql注入防止上。thinkphp的处理方式
ThinkPHP\Library\Think\Model.class.php里面有如下的代码
  1. protected function parseSql($sql,$parse) {
  2.         // 分析表达式
  3.         if(true === $parse) {
  4.             $options =  $this->_parseOptions();
  5.             $sql    =   $this->db->parseSql($sql,$options);
  6.         }elseif(is_array($parse)){ // SQL预处理
  7.             $parse  =   array_map(array($this->db,'escapeString'),$parse);
  8.             $sql    =   vsprintf($sql,$parse);
  9.         }else{
  10.             $sql    =   strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX')));
  11.         }
  12.         $this->db->setModel($this->name);
  13.         return $sql;
  14.     }
复制代码
array_map(array($this->db,'escapeString'),$parse);
关键是调用了对应的数据库类型里面的escapeString进行处理。因为php通常和mysql作为搭配,我就看了一下mysql的处理。里面包括了mysql和mysqli的处理代码
mysql版本的处理
  1. public function escapeString($str) {
  2.         if($this->_linkID) {
  3.             return mysql_real_escape_string($str,$this->_linkID);
  4.         }else{
  5.             return mysql_escape_string($str);
  6.         }
  7.     }
复制代码
mysqli的处理方式。
  1. public function escapeString($str) {
  2.         if($this->_linkID) {
  3.             return  $this->_linkID->real_escape_string($str);
  4.         }else{
  5.             return addslashes($str);
  6.         }
  7.     }
复制代码
看似很正常的处理方式,但是你们明白addslashes、mysql_escape_string、mysql_real_escape_string它们的真正的安全性吗,下面这些文章会让你明白的。
http://blog.youkuaiyun.com/felio/article/details/1226569
按照文章的说明,测试代码test.php,文件保存为gbk格式测试一下就明白addslashes安全性了
  1. <?php
  2. error_reporting(0);
  3. header('Content-Type: text/html; charset=gbk');  
  4. $username = $_POST['username'];  
  5.     $sqlx="select id,isDisplay from user where usname='".addslashes($username)."' and passwd='$password'";
  6.     echo $sqlx;
  7.     echo "<br>";
  8.     echo addslashes($username);
  9.     echo 444;
  10.  ?>
  11.  <form action="" method=post>
  12.  <input type=text name="username" value="">
  13.  <input type=submit>
  14.  </form>
复制代码
下面还有一个连接地址,详细说明了关于addslashes、mysql_escape_string、mysql_real_escape_string的安全性问题。而且这个问题早在2006年就被提出了哦,thinkphp还是不重视
http://blog.youkuaiyun.com/zhuizhuziwo/article/details/8525789
最后说一句,按照php官方说法,最好用pdo的预处理,看看thinkphp的封装,完全是误人子弟
ThinkPHP\Library\Think\Db\Driver\Pdo.class.php
  1. protected function parseValue($value) {
  2.         if(is_string($value)) {
  3.             $value =  strpos($value,':') === 0 ? $this->escapeString($value) : '\''.$this->escapeString($value).'\'';
  4.         }elseif(isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp'){
  5.             $value =  $this->escapeString($value[1]);
  6.         }elseif(is_array($value)) {
  7.             $value =  array_map(array($this, 'parseValue'),$value);
  8.         }elseif(is_bool($value)){
  9.             $value =  $value ? '1' : '0';
  10.         }elseif(is_null($value)){
  11.             $value =  'null';
  12.         }
  13.         return $value;
  14.     }
  15.  public function escapeString($str) {
  16.          switch($this->dbType) {
  17.             case 'PGSQL':
  18.             case 'MSSQL':
  19.             case 'SQLSRV':
  20.             case 'MYSQL':
  21.                 return addslashes($str);
  22.             case 'IBASE':                
  23.             case 'SQLITE':
  24.             case 'ORACLE':
  25.             case 'OCI':
  26.                 return str_ireplace("'", "''", $str);
  27.         }
  28.     }
复制代码
一点预处理的东西都没有,到处充斥着addslashes、mysql_escape_string、mysql_real_escape_string看懂了吧。这个封装就是骗小孩的把戏
不多吐槽了。按照php官方说法,大家还是老老实实用pdo的参数绑定方式吧。
下面是参考文章对于pdo有详细说明
http://zhangxugg-163-com.iteye.com/blog/1835721
http://zhangxugg-163-com.iteye.com/blog/1850461
修复ThinkPHP框架安全漏洞需要采取一系列系统性的措施,以确保网站和用户数据的安全性。以下是几种有效的修复方法: 1. **及时更新到最新版本** 官方通常会发布新版本来修复已知的安全漏洞。因此,定期检查并更新到ThinkPHP的最新版本是防止安全问题的重要步骤。例如,官方对ThinkPHP 5.0到5.1的所有版本进行了升级,并修复了一些关键漏洞,如SQL注入漏洞和远程代码执行漏洞[^2]。 2. **手动修补核心文件** 如果无法立即升级到最新版本,可以手动修补核心文件。这包括替换旧的核心文件为最新版本中的对应文件,并清除缓存目录(如`runtime`文件夹),以便在下次运行时重新生成新的缓存内容[^4]。 3. **防范SQL注入漏洞** SQL注入是一种常见的攻击方式,可以通过使用参数化查询或预处理语句来避免。此外,应严格过滤用户输入的数据,避免直接将其拼接到SQL语句中。 4. **防御远程代码执行漏洞** ThinkPHP的远程代码执行漏洞通常与框架的某些动态功能有关,例如通过URL调用特定函数。为了防范此类攻击,应禁用不必要的动态执行功能,并对用户输入进行严格的验证和过滤。例如,避免将用户输入直接用于执行系统命令,或者限制可调用的函数范围。 5. **设置文件权限和路径保护** 对于可能被利用写入恶意脚本的目录(如Web根目录下的上传目录),应限制其文件权限,禁止执行PHP脚本。同时,确保配置文件和其他敏感文件不在Web根目录下,而是存储在不可公开访问的路径中。 6. **启用安全日志监控** 配置服务器以记录所有可疑活动的日志,例如异常的请求模式或尝试访问未授权资源的行为。通过分析这些日志,可以更快地发现潜在的安全威胁。 7. **使用防火墙和安全工具** 使用Web应用防火墙(WAF)可以帮助检测和阻止恶意流量。此外,定期使用自动化安全扫描工具对网站进行全面检查,识别并修复潜在漏洞。 ### 示例:手动修补ThinkPHP核心文件 如果选择手动修补而非完全升级,可以参考以下步骤: ```bash # 删除旧的ThinkPHP核心文件 rm -rf /path/to/your/project/thinkphp # 替换为最新版本的核心文件 cp -r /path/to/new/thinkphp /path/to/your/project/ # 清除缓存目录 rm -rf /path/to/your/project/runtime/* ``` ### 示例:防范远程代码执行漏洞 在代码中避免使用用户输入直接执行系统命令,例如以下不安全的代码片段: ```php // 不安全的代码示例 $command = $_GET['cmd']; system($command); ``` 应改写为允许白名单中的命令执行: ```php // 更安全的代码示例 $allowedCommands = ['list_files', 'check_status']; $command = $_GET['cmd']; if (in_array($command, $allowedCommands)) { // 执行对应的预定义操作 switch ($command) { case 'list_files': system('ls'); break; case 'check_status': system('echo "System is running normally."'); break; } } else { echo "Invalid command."; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值