配置选项

phpinfo( ) 函数可用于php.ini文件的定位

A.1. allow_url_fopen

选项允许你如同本地文件一样引用远程资源:

我推荐关闭allow_url_fopen选项,除非你的应用需要它。

A.2. disable_functions

disable_functions选项是非常有用的,它可以确保一些有潜在威胁的函数不能被使用。尽管可以建立规范去禁止使用这些函数,但在PHP配置中进行限制要比依赖于开发者对规范的遵循要可靠得多。

我建立对附录B列出的函数进行检查,看一下是否要对一些函数进行限制。

A.3. display_errors

PHP的错误报告可以帮助你发现你所写代码中的错误。当你开发应用时,把错误提示显示出来是取得即时反馈的有效方法,同时也可以加快开发速度。

在一个产品级的应用中,这一行为会成为一项安全风险。如果它显示错误信息,所有人就可以得知你的应用中的重要信息。

在产品中你需要关闭display_errors选项。

A.4. enable_dl

enable_dl选项用于控制dl()函数是否生效,该函数允许在运行时加载PHP扩展。

使用dl()函数可能导致攻击者绕过open_basedir限制,因此除非有必要,你必须在你的应用中禁止它。 (利用方法

A.5. error_reporting

很多安全漏洞是由于使用了未初始化的变量或其它随意的编程方法引起的。通过把PHP的error_reporting选项置为E_ALL 或 E_ALL | E_STRICT,PHP就会对上述行为进行提示。这些设置都为报告Notice级别的错误。

我建议把error_reporting至少设定为E_ALL。(译注:在开发中)

A.6. file_uploads

file_uploads选项决定了是否允许上传文件。因此,如果你的应用不需要用户上传文件,那么关闭该选项就是最好的选择。

只是简单地在PHP代码中不对上传文件进行处理是不够的,因为在执行你的代码前,PHP就做了一些工作(如根据相关部据生成$_FILES数组)。

A.7. log_errors

当log_errors设为有效时,PHP会向error_log配置选项指定的文件中写入所有出错信息。

当display_errors设为无效时,将log_errors设为有效是很重要的;否则你将无法看到睛出错信息。

我建议将log_errors设为有效并在error_log设定日志文件所在位置。

A.8. magic_quotes_gpc

magic_quotes_gpc是一个常用的选项,它目的是防止SQL注入。但出于很多原因,包括它转义输入的方式,证明了它是不完善的。

它对$_GET, $_POST, 以及 $_COOKIE中的数据使用同样的规则即addslashes( )函数进行处理。从而,它并没有根据你的数据库选用对应的转义函数进行处理。

基于两个主要的原因,你需要把get_magic_quotes_gpc设为无效:

首先,它会加大你的输入过滤逻辑的复杂性,这是由于它在执行你的代码前首先对数据进行了编辑。例如,你需要对输入的姓名进行过滤,其逻辑是只允许字母、空格、连词符以及单引号,当magic_quotes_gpc生效时,你必须适应形如O\'Reilly的姓名或者使用stripslashes( )尝试将它恢复原形。这一不必要的复杂性(或者说不严谨的过滤规则)加大了发生错误的可能性,同时,你的输入过滤机制中的缺陷必然会导致安全漏洞。

其次,它并没有根据你的数据库选用对应的转义函数进行处理。这样,由于它可以抵挡一些低层次或偶发的攻击,掩盖了它是一个糟糕的过滤或转义机制这个事实,从而留下了一个安全漏洞,使你的应用无法抵挡如针对字符集的攻击等更复杂的攻击手段。

A.9. memory_limit

为防止写得糟糕的脚本占用所有的可用内存,可以使用memory_limit选项对最大内存使用量进行限制(以字节方式或缩写方式如8M指定)。

尽管最佳的取值是与运行的应用是相关的,我还是建议在大多情况下使用默认值8M。

memory_limit选项只有在PHP指定了enable-memory-limit方式编译时才会生效。

A.10. open_basedir

open_basedir选项会限制PHP只能在它指定的目录中打开文件。尽管它不能取代正确的输入过滤,但该选项能减少利用文件系统相关函数如include及require进行的攻击。

该选项的值会被当做前缀使用,因此当你想表示指定目录时请小心不要漏了最后的斜杠:

open_basedir = /path/to/

小提示

请确认enable_dl选项是关闭的,否则open_basedir的限制可能会被绕过。

安全人员 - 数据 加密 解密:

加密

  作为一本相关安全方面的书,通常加密是需要提及的话题。我之所以在本书的主体部分忽略了加密问题,是因为它的用途是狭窄的,而开发者应从大处着眼来考虑安全问题。过分依赖于加密常常会混淆问题的根源。尽管加密本身是有效的,但是进行加密并不会神奇地提高一个应用的安全性。

  一个PHP开发人员应主要熟悉以下的加密方式:

l        对称加密

l        非对称加密(公钥)

l        Hash函数(信息摘要)

l        信息验证码

  本附录主要关注于使用mcrypt扩展的对称加密算法。你需要参考的资料如下:

  实用加密技术(Applied Cryptography), by Bruce Schneier (Wiley)

http://www.schneier.com/blog/

http://wikipedia.org/wiki/Cryptography

http://phpsec.org/articles/2005/password-hashing.html

http://pear.php.net/package/Crypt_HMAC

http://pear.php.net/package/Crypt_RSA

C.1. 密码的存储

  当你在数据库内存储的密码时,永远不要以明码方式存入,而是应该存储密码的hash值并同时使用附加字串:

  <?php

  /* $password contains the password. */

  $salt = 'SHIFLETT';

  $password_hash = md5($salt . md5($password . $salt));

  /* Store password hash. */

  ?>

  当你需要确认一个密码是否正确时,以同样的方式计算出hash值并比较异同:

  <?php

  $salt = 'SHIFLETT';

  $password_hash = md5($salt . md5($_POST['password'] . $salt));

  /* Compare password hashes. */

  ?>

  如果hash值完全相同,你就有理由认为密码也是相同的。

  如果使用了这个技巧,是不可能告诉用户他们的密码是什么的。当用户忘记密码时,你只能让他录入一个新密码并重新计算hash值存入数据库。当然,你需要非常小心地对用户进行身份确认——密码提醒机制是易受频繁攻击的目标,同时也是经常出现安全漏洞的源头。

C.2. 使用mcrypt

  PHP的标准加密扩展是mcrypt,它支持很多不同的加密算法。你可以通过mcrypt_list_algorithms( )函数来查看你的平台上支持的算法列表:

  <?php

  echo '<pre>' . print_r(mcrypt_list_algorithms(), TRUE) . '</pre>';

  ?>

  加密和解密分别由mcrypt_encrypt( ) 及 mcrypt_decrypt( )函数来实现。这两个函数都有5个参数,第一个参数是用于指定使用的算法:

  <?php

  mcrypt_encrypt($algorithm,

                 $key,

                 $cleartext,

                 $mode,

                 $iv);

  mcrypt_decrypt($algorithm,

                 $key,

                 $ciphertext,

                 $mode,

                 $iv);

  ?>

  其中的加密键(第二个参数)是非常敏感的数据,因此你要确保把它存放在安全的地方。可以用第八章中保护数据库权限的方法来保护加密键。如果经济条件允许的话,硬件加密键是最好的选择,它提供了超级强大的安全性。

  函数有多种模式可供选择,你可以使用mcrypt_list_modes( )来列出所有支持的模式:

  <?php

  echo '<pre>' . print_r(mcrypt_list_modes(), TRUE) . '</pre>';

  ?>

  第五个参数($iv)为初始化向量,可以使用mcrypt_create_iv( )函数建立。

  下面的示例类提供了基本的加密解密方法:

  class crypt

  {

    private $algorithm;

    private $mode;

    private $random_source;

    public $cleartext;

    public $ciphertext;

    public $iv;

    public function __construct($algorithm = MCRYPT_BLOWFISH,

                                $mode = MCRYPT_MODE_CBC,

                                $random_source = MCRYPT_DEV_URANDOM)

    {

      $this->algorithm = $algorithm;

      $this->mode = $mode;

      $this->random_source = $random_source;

    }

    public function generate_iv()

    {

      $this->iv = mcrypt_create_iv(mcrypt_get_iv_size($this->algorithm,

        $this->mode), $this->random_source);

    }

    public function encrypt()

    {

      $this->ciphertext = mcrypt_encrypt($this->algorithm,

        $_SERVER['CRYPT_KEY'], $this->cleartext, $this->mode, $this->iv);

    }

    public function decrypt()

    {

      $this->cleartext = mcrypt_decrypt($this->algorithm,

        $_SERVER['CRYPT_KEY'], $this->ciphertext, $this->mode, $this->iv);

    }

  }

  ?>

  上面的类会在其它示例中使用,下面是它的使用方法示例:

  <?php

  $crypt = new crypt();

  $crypt->cleartext = 'This is a string';

  $crypt->generate_iv();

  $crypt->encrypt();

  $ciphertext = base64_encode($crypt->ciphertext);

  $iv = base64_encode($crypt->iv);

  unset($crypt);

  /* Store $ciphertext and $iv (initialization vector). */

  $ciphertext = base64_decode($ciphertext);

  $iv = base64_decode($iv);

  $crypt = new crypt();

  $crypt->iv = $iv;

  $crypt->ciphertext = $ciphertext;

  $crypt->decrypt();

  $cleartext = $crypt->cleartext;

  ?>

小提示

  本扩展要求你在编译PHP时使用-mcrypt标识。安装指南及要求详见http://php.net/mcrypt。

C.3. 信用卡号的保存

  我常常被问到如何安全地保存信用卡号。我的总是会首先询问他们是否确实有必要保存信用卡号。毕竟不管具体是如何操作的,引入不必要的风险是不明智的。同时国家法律还有关于信用卡信息处理方面的规定,我还时刻小心地提醒我并不是一个法律专家。

  本书中我并不会专门讨论信用卡处理的方法,而是会说明如何保存加密信息到数据库及在读取时解密。该流程会导致系统性能的下降,但是确实提供了一层保护措施。其主要优点是如果数据库内容泄密暴露出的只是加密信息,但是前提是加密键是安全的。因此,加密键与加密的实现方法本身同样重要。

  保存加密数据到数据的过程是,首先加密数据,然后通过初始向量与明文建立密文来保存到数据库。由于密文是二进制字符串,还需要通过base64_encode( )转换成普通文本字符串以保证二进制编码的安全存储。

  <?php

  $crypt = new crypt();

  $crypt->cleartext = '1234567890123456';

  $crypt->generate_iv();

  $crypt->encrypt();

  $ciphertext = $crypt->ciphertext;

  $iv = $crypt->iv;

  $string = base64_encode($iv . $ciphertext);

  ?>

  保存该字串至数据库。在读取时,则是上面流程的逆处理:

  <?php

  $string = base64_decode($string);

  $iv_size = mcrypt_get_iv_size($algorithm, $mode);

  $ciphertext = substr($string, $iv_size);

  $iv = substr($string, 0, $iv_size);

  $crypt = new crypt();

  $crypt->iv = $iv;

  $crypt->ciphertext = $ciphertext;

  $crypt->decrypt();

  $cleartext =  $crypt->cleartext;

  ?>

  本实现方法假定加密算法与模式不变。如果它们是不定的话,你还要保存它们以用于解密数据。加密键是唯一需要保密的数据。

C.4. 加密会话数据

  如果你的数据库存在安全问题,或者部分保存在会话中的数据是敏感的,你可能希望加密会话数据。除非很有必要,一般我不推荐这样做,但是如果你觉得在你的情形下需要这样做的话,本节提供了一个实现方法的示例。

  这个方案十分简单。实际上,在第八章中,已经说明了如何通过调用session_set_save_handler( )来执行你自己的会话机制。通过对保存和读取数据的函数的少量调整,你就能加密存入数据库的数据及在读取时解密数据:

  <?php

  function _read($id)

  {

    global $_sess_db;

    $algorithm = MCRYPT_BLOWFISH;

    $mode = MCRYPT_MODE_CBC;

    $id = mysql_real_escape_string($id);

    $sql = "SELECT data

            FROM   sessions

            WHERE  id = '$id'";

    if ($result = mysql_query($sql, $_sess_db))

    {

        $record = mysql_fetch_assoc($result);

        $data = base64_decode($record['data']);

        $iv_size = mcrypt_get_iv_size($algorithm, $mode);

        $ciphertext = substr($data, $iv_size);

        $iv = substr($data, 0, $iv_size);

        $crypt = new crypt();

        $crypt->iv = $iv;

        $crypt->ciphertext = $ciphertext;

        $crypt->decrypt();

        return $crypt->cleartext;

    }

    return '';

  }

  function _write($id, $data)

  {

    global $_sess_db;

    $access = time();

    $crypt = new crypt();

    $crypt->cleartext = $data;

    $crypt->generate_iv();

    $crypt->encrypt();

    $ciphertext = $crypt->ciphertext;

    $iv = $crypt->iv;

    $data = base64_encode($iv . $ciphertext);

    $id = mysql_real_escape_string($id);

    $access = mysql_real_escape_string($access);

    $data = mysql_real_escape_string($data);

    $sql = "REPLACE

            INTO    sessions

            VALUES  ('$id', '$access', '$data')";

    return mysql_query($sql, $_sess_db);

  }

PHP 如何 安全配置的更多相关文章

  1. 配置android sdk 环境

    1:下载adnroid sdk安装包 官方下载地址无法打开,没有vpn,使用下面这个地址下载,地址:http://www.android-studio.org/

  2. Android Studio配置 AndroidAnnotations——Hi_博客 Android App 开发笔记

    以前用Eclicps 用习惯了现在 想学学 用Android Studio 两天的钻研终于 在我电脑上装了一个Android Studio 并完成了AndroidAnnotations 的配置. An ...

  3. react-router 组件式配置与对象式配置小区别

    1. react-router 对象式配置 和 组件式配置    组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...

  4. 总结:Mac前端开发环境的搭建(配置)

    新年新气象,在2016年的第一天,我入手了人生中第一台自己的电脑(大一时好友赠送的电脑在一次无意中烧坏了主板,此后便不断借用别人的或者网站的).macbook air,身上已无分文...接下来半年的房 ...

  5. Android Studio 多个编译环境配置 多渠道打包 APK输出配置

    看完这篇你学到什么: 熟悉gradle的构建配置 熟悉代码构建环境的目录结构,你知道的不仅仅是只有src/main 开发.生成环境等等环境可以任意切换打包 多渠道打包 APK输出文件配置 需求 一般我 ...

  6. Virtual Box配置CentOS7网络(图文教程)

    之前很多次安装CentOS7虚拟机,每次配置网络在网上找教程,今天总结一下,全图文配置,方便以后查看. Virtual Box可选的网络接入方式包括: NAT 网络地址转换模式(NAT,Network ...

  7. [linux]阿里云主机的免登陆安全SSH配置与思考

    公司服务器使用的第三方云端服务,即阿里云,而本地需要经常去登录到服务器做相应的配置工作,鉴于此,每次登录都要使用密码是比较烦躁的,本着极速思想,我们需要配置我们的免登陆. 一 理论概述 SSH介绍 S ...

  8. nginx配置反向代理或跳转出现400问题处理记录

    午休完上班后,同事说测试站点访问接口出现400 Bad Request  Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...

  9. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  10. 在 ML2 中配置 OVS flat network - 每天5分钟玩转 OpenStack(133)

    前面讨论了 OVS local network,今天开始学习 flat network. flat network 是不带 tag 的网络,宿主机的物理网卡通过网桥与 flat network 连接, ...

随机推荐

  1. b3_trcd_EDCD_new

    # -*- coding:utf-8 -*- import re year="17A" ss='./data/' filename = ss+'EDCD%s.txt'%year ' ...

  2. @WebService @WebMethod 详解

    形象图解 首先AB均需要@WebService如果 @WebService(endpointInterface="package.B") public class A implem ...

  3. pathinfo()在php不同版本中对于对多字节字符处理的不同结果

    phpinfo()函数在处理路径时,在php的低版本中无法处理多字节字符,这里测试的是php5.3和php5.6 的区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  4. noip第7课作业

    1.    求平均值 [问题描述] 在一次运动会方队表演中,学校安排了十名老师进行打分.对于给定的每个参赛班级的不同打分(百分制整数),按照去掉一个最高分.去掉一个最低分,再算出平均分的方法,得到改班 ...

  5. 评论:一套Developer Express控件包 For Delphi7

    http://www.2ccc.com/idea.asp?articleid=1675 (也可以查看盒子上这个帖子的内容) Developer Express Inc 系列控件组 for Delphi ...

  6. Python学习-37.Python中的正则表达式

    作为一门现代语言,正则表达式是必不可缺的,在Python中,正则表达式位于re模块. import re 这里不说正则表达式怎样去匹配,例如\d代表数字,^代表开头(也代表非,例如^a-z则不匹配任何 ...

  7. dstat常用参数组合

    io/if/vm三合一 dstat -cdlmnpsy dstat --top-mem --top-cpu --top-io

  8. OPC测试常用的OPCClient和OPCServer软件推荐

    各位在进行OPC通讯时,常会遇到两种情况: 1)使用一个OPCClient在同一台计算机上连接远程计算机上的多个OPCServer时,发现某个OPCServer是通畅的,但其他的OPCServer却无 ...

  9. WPF 获取表格里面的内容

    DataRowView dataRow = DataGridCase.SelectedItem as DataRowView; 代码转为数组分别获取.

  10. 基于MVC框架layui分页控件实现前端分页信息写法

    详细链接:https://shop499704308.taobao.com/?spm=a1z38n.10677092.card.11.594c1debsAGeak@{ ViewBag.Title = ...