PHP Cookbook读书笔记 – 第18章安全和加密

概述

很多WEB应用程序的安全问题多是由于轻信第三方提供的数据造成的,如将未经过滤的数据发送到浏览器就可能造成跨站点脚本攻击(XSS),如果将未经过滤的数据发送到数据库就可能造成数据库注入(SQL injection)过滤数据并不能解决所有的安全问题,因为造成安全问题的起因还包括session的定置攻击,伪造跨站点请求等,另外可以通过加密提高本地数据的安全性,通过SSL提高数据在用户与服务器之间传输的安全性。

预防Session定置攻击

Session定置攻击在session一章一节做过介绍,就是攻击者如果知道用户的session id可以伪造其信息来获取用户的信息。所有避免将session以url方式传递以及通过一些技术手段获取真实用户的其他独特信息并与session信息一起做比较来判断以提高其安全性。例如淘宝的支付宝就会通过分析用户IP记录每次用户支付时的所在地,如果用户在支付时在异地,即使支付密码正确,支付证书无误,也会弹出安全验证。这就是典型的多信息验证以提高安全性的例子。

防止表单提交欺骗

本节主要介绍如何有效防止跨站请求伪造(Cross Site Request Forgery即CSRF)攻击,这些攻击都是在受骗者不知情的情况下,让受骗者像某个站点发送请求提交数据来达到攻击的目的,通常,受骗者对该站点都具备一定的授权。为避免这种情况发生而采取的在用户显示表单页时分配一个唯一的session值,在用户提交表单时核查该值,如果一致表示是由用户发起的而不是攻击者或攻击程序。

过滤提交的数据

对用户提交的数据进行必要的过滤可以减少很多安全隐患。

//实际开发中可以使用addslashes和mysql的语句过滤用户的输入
 if (!get_magic_quotes_gpc()) {
        return addslashes($str);
    }
 mysql_real_escape_string("用户输入字符串");

避免跨站脚本攻击(XSS)

跨站脚本攻击(Cross Site Scripting)是利用网站漏洞从用户那里恶意盗取信息。XSS攻击的目的是盗走客户端cookies,或者任何可以用于在web站点确定客户身份的其他敏感信息。手边有了合法用户的标记,黑客可以继续扮演用户与网站交互,从而冒充用户。

如何避免跨站脚本攻击:

  • 验证用户的输入
  • 对输出进行编码
  • 明确指明输出编码方式
  • 对存入数据库的数据进行严格过滤

避免SQL注入(SQL injection)

SQL注入攻击通常通过给站点数据库提交不良或查询语句来实现,很可能造成数据库的数据暴露、更改或删除。官方针对这个内容专门写了一个主题,关于SQL注入攻击的定义可以看百度百科2-1

图片来源51CTO.COM

如何避免SQL注入攻击:

  • 所有非数值类型的SQL变量都加上引号(magic_quotes_gpc或者addslashes)
  • 所有非数值类型做转义(convertStr())
  • 对于数值类型的做到预先判定其类型(convertNum())
  • 在生产环境关闭错误显示

密码的安全措施

  • 密码置于站点文件外,避免通过互联网直接访问
  • 不以明文存储密码,密码都经过加密保存,尽可能使用无法反向解密的加密方式
  • 对于遗忘密码的用户,采用邮件重设密码(而不是邮件找回密码)

加密和解密数据

本机测试mcrypt需要确定是否已经启用了mcrypt扩展,可通过phpinfo()查看,mcrypt扩展支持很多种加密解密模型,下图中高亮部分表示目前环境支持的模型

捕获

mcrypt主要支持四种块加密模型,简要说明如下:

  • MCRYPT_MODE_ECB(electronic codebook)适合对小数量随机数据加密,如登录密码
  • MCRYPT_MODE_CBC(cipher block chaining)适合加密安全级别较高的重要文件类型
  • MCRYPT_MODE_CFB(cipher feedback)适合于需要对数据流的每一个字节进行加密的场合
  • MCRYPT_MODE_OFB(output feedback,in 8bit)和CFB相似,CFB会引起加密的错误扩散,如果一个byte错误,则其后的所有byte都会出错。OFB不会没这个问题,但由于OFB是8bit的导致它并不安全,所有不推荐使用
  • MCRYPT_MODE_NOFB(output feedback,in nbit)和OFB相似,但更加的安全因为它采用了块操作算法
  • MCRYPT_MODE_STREAM是为了WAKE或者RC4等流加密算法提供的额外模型

看个官方提供的例子

$key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

例子中通过mcrypt_create_iv 函数生成一个随机的唯一IV向量,但如果你打算将加密和解密过程分成2个文件保存,注意这里的$iv值需要保持一致,也就是说不能使用这个函数来生成加密向量。

保存加密数据到文件或数据库

如果你打算将加密数据保存到文件或数据库除了保存加密后的数据以外,还需要保存解密数据时所需的信息(例如算法、加密模式和加密向量等)但不包括密钥。

而常见的情形是在某web应用中的某功能模块加密算法与加密模式是事先固定的,只有向量是随加密的用户信息保存到了数据库中。

在网站之间传递加密数据

网站间的数据传递是有可能被第三方截获到的,所有对敏感数据进行加密是必须的,如果要保证网站间的数据传递更加安全,可以考虑通过SSL来实现。

posted @ 2011-11-19 15:54  涂文瀚  阅读(555)  评论(0编辑  收藏  举报
foot