【安全开发】PHP安全编码规范

申明:本文非笔者原创,原文转载自:https://github.com/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%84%E8%8C%83%E6%96%87%E6%A1%A3/2018-08-17-SDL-2-php%E5%AE%89%E5%85%A8%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83.md

1.配置

php.ini基本安全配置


1.1应启用“cgi.force_redirect”

cgi.force_redirect在php.ini中修改,默认是开启的,它可以防止当PHP运行的CGI脚本未经验证的访问。在IIS,OmniHTTPD和Xitami上是禁用的,但在所有其他情况下它应该打开。

; php.ini
cgi.force_redirect=1 ; 

1.2应禁用“enable_dl”

该指令仅对Apache模块版本的PHP有效。你可以针对每个虚拟机或每个目录开启或关闭dl()动态加载PHP模块。关闭动态加载的主要原因是为了安全。通过动态加载,有可能忽略所有open_basedir限制。默认允许动态加载,除了使用安全模式。在安全模式,总是无法使用dl()。

; php.ini
enable_dl=0 ; 

1.3应禁用“file_uploads”

file_uploads默认是开启的,允许将文件上传到您的站点。因为来自陌生人的文件本质上是不可信甚至危险的,除非您的网站绝对需要,否则应禁用此功能。如果开启请进行相应的限制,参考upload_max_filesize, upload_tmp_dir,和post_max_size。

; php.ini
file_uploads = 0 ; 

1.4通过“open_basedir”限制文件访问权限

open_basedir默认是打开所有文件,它将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令不受安全模式打开或者关闭的影响。当一个脚本试图用例如 fopen() ,include或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。

open_basedir应该配置一个目录,然后可以递归访问。但是,应该避免使用. (当前目录)作为open_basedir值,因为它在脚本执行期间动态解析特殊值 . 指明脚本的工作目录将被作为基准目录,但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。

在 httpd.conf 文件中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的方法关闭(例如某些虚拟主机中)。在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。

用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:“open_basedir = /dir/incl/”。

; php.ini
open_basedir="${USER}/scripts/data" ; 

1.5应禁用“session.use_trans_sid”

默认为 0(禁用)。当禁用cookie时,如果它开启,PHP会自动将用户的会话ID附加到URL。基于 URL 的会话管理比基于 cookie 的会话管理有更多安全风险,从表面上看,这似乎是让那些禁用cookie的用户正常使用您的网站的好方法。实际上,它使那些用户容易被任何人劫持他们的会话。例如用户有可能通过 email 将一个包含有效的会话 ID 的 URL 发给他的朋友,或者用户总是有可能在收藏夹中存有一个包含会话 ID 的 URL 来以同样的会话 ID 去访问站点。也可以从浏览器历史记录和服务器日志中检索URL获取会话ID。

; php.ini
session.use_trans_sid = 0 ; 

1.6会话管理cookie不能是持久的

没有固定生命周期或到期日期的Cookie被称为非持久性或“会话”cookie,这意味着它们只会持续与浏览器会话一样长,并且在浏览器关闭时会消失。具有到期日期的Cookie叫做“持久性”Cookie,他们将被存储/保留到这些生存日期。

管理网站上的登录会话应用非持久性cookie。要使cookie非持久化,只需省略该 expires属性即可。也可以使用session.cookie_lifetime实现。


1.7应禁用"allow_url_fopen"和"allow_url_include"

allow_url_fopen和allow_url_include默认是开启的,他们允许代码从URL中读入脚本。从站点外部吸入可执行代码的能力,加上不完美的输入清理可能会使站点裸露给攻击者。即使该站点的输入过滤在今天是完美的,但不能保证以后也是。

; php.ini
allow_url_fopen = 0
allow_url_include = 0

2.编码

php安全编码建议


2.1慎用sleep()函数

sleep()有时用于通过限制响应率来防止拒绝服务(DoS)攻击。但是因为它占用了一个线程,每个请求需要更长的时间来服务,这会使应用程序更容易受到DoS攻击,而不是减少风险。

if (is_bad_ip($requester)) {
  sleep(5);  // 不合规的用法
}

2.2禁止代码动态注入和执行

eval()函数是一种在运行时运行任意代码的方法。 函数eval()语言结构是非常危险的,因为它允许执行任意 PHP 代码。因此不鼓励使用它。如果您仔细的确认过,除了使用此结构以外别无方法,请多加注意,不要允许传入任何由用户提供的、未经完整验证过的数据。

eval($code_to_be_dynamically_executed)  // 不合规的用法

2.3禁止凭据硬编码

因为从编译的应用程序中提取字符串很容易,所以永远不应对凭证进行硬编码。对于分发的应用程序尤其如此。 凭据应存储在受强保护的加密配置文件或数据库中的代码之外。

// 合规的用法
$uname = getEncryptedUser();
$password = getEncryptedPass();
connect($uname, $password); 
// 不合规的用法
$uname = "steve";
$password = "blue";
connect($uname, $password);

 

 

1.配置

php.ini基本安全配置


1.1应启用“cgi.force_redirect”

cgi.force_redirect在php.ini中修改,默认是开启的,它可以防止当PHP运行的CGI脚本未经验证的访问。在IIS,OmniHTTPD和Xitami上是禁用的,但在所有其他情况下它应该打开。

; php.ini
cgi.force_redirect=1 ; 

1.2应禁用“enable_dl”

该指令仅对Apache模块版本的PHP有效。你可以针对每个虚拟机或每个目录开启或关闭dl()动态加载PHP模块。关闭动态加载的主要原因是为了安全。通过动态加载,有可能忽略所有open_basedir限制。默认允许动态加载,除了使用安全模式。在安全模式,总是无法使用dl()。

; php.ini
enable_dl=0 ; 

1.3应禁用“file_uploads”

file_uploads默认是开启的,允许将文件上传到您的站点。因为来自陌生人的文件本质上是不可信甚至危险的,除非您的网站绝对需要,否则应禁用此功能。如果开启请进行相应的限制,参考upload_max_filesize, upload_tmp_dir,和post_max_size。

; php.ini
file_uploads = 0 ; 

1.4通过“open_basedir”限制文件访问权限

open_basedir默认是打开所有文件,它将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令不受安全模式打开或者关闭的影响。当一个脚本试图用例如 fopen() ,include或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。

open_basedir应该配置一个目录,然后可以递归访问。但是,应该避免使用. (当前目录)作为open_basedir值,因为它在脚本执行期间动态解析特殊值 . 指明脚本的工作目录将被作为基准目录,但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。

在 httpd.conf 文件中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的方法关闭(例如某些虚拟主机中)。在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。

用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:“open_basedir = /dir/incl/”。

; php.ini
open_basedir="${USER}/scripts/data" ; 

1.5应禁用“session.use_trans_sid”

默认为 0(禁用)。当禁用cookie时,如果它开启,PHP会自动将用户的会话ID附加到URL。基于 URL 的会话管理比基于 cookie 的会话管理有更多安全风险,从表面上看,这似乎是让那些禁用cookie的用户正常使用您的网站的好方法。实际上,它使那些用户容易被任何人劫持他们的会话。例如用户有可能通过 email 将一个包含有效的会话 ID 的 URL 发给他的朋友,或者用户总是有可能在收藏夹中存有一个包含会话 ID 的 URL 来以同样的会话 ID 去访问站点。也可以从浏览器历史记录和服务器日志中检索URL获取会话ID。

; php.ini
session.use_trans_sid = 0 ; 

1.6会话管理cookie不能是持久的

没有固定生命周期或到期日期的Cookie被称为非持久性或“会话”cookie,这意味着它们只会持续与浏览器会话一样长,并且在浏览器关闭时会消失。具有到期日期的Cookie叫做“持久性”Cookie,他们将被存储/保留到这些生存日期。

管理网站上的登录会话应用非持久性cookie。要使cookie非持久化,只需省略该 expires属性即可。也可以使用session.cookie_lifetime实现。


1.7应禁用"allow_url_fopen"和"allow_url_include"

allow_url_fopen和allow_url_include默认是开启的,他们允许代码从URL中读入脚本。从站点外部吸入可执行代码的能力,加上不完美的输入清理可能会使站点裸露给攻击者。即使该站点的输入过滤在今天是完美的,但不能保证以后也是。

; php.ini
allow_url_fopen = 0
allow_url_include = 0

2.编码

php安全编码建议


2.1慎用sleep()函数

sleep()有时用于通过限制响应率来防止拒绝服务(DoS)攻击。但是因为它占用了一个线程,每个请求需要更长的时间来服务,这会使应用程序更容易受到DoS攻击,而不是减少风险。

if (is_bad_ip($requester)) {
  sleep(5);  // 不合规的用法
}

2.2禁止代码动态注入和执行

eval()函数是一种在运行时运行任意代码的方法。 函数eval()语言结构是非常危险的,因为它允许执行任意 PHP 代码。因此不鼓励使用它。如果您仔细的确认过,除了使用此结构以外别无方法,请多加注意,不要允许传入任何由用户提供的、未经完整验证过的数据。

eval($code_to_be_dynamically_executed)  // 不合规的用法

2.3禁止凭据硬编码

因为从编译的应用程序中提取字符串很容易,所以永远不应对凭证进行硬编码。对于分发的应用程序尤其如此。 凭据应存储在受强保护的加密配置文件或数据库中的代码之外。

// 合规的用法
$uname = getEncryptedUser();
$password = getEncryptedPass();
connect($uname, $password); 
// 不合规的用法
$uname = "steve";
$password = "blue";
connect($uname, $password);

转载于:https://www.cnblogs.com/xiaozi/p/10044570.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 1 PHP接口安全 4 1.1 指定公布给外部的资源,客户端只能访问允许访问的资源 4 1.1.1 说明 4 1.1.2 应对 4 1.1.3 举例 4 1.2 定义所有接口的参数,并做严格的检查 5 1.2.1 说明 5 1.2.2 应对 5 1.2.3 举例 5 1.3 不能让客户端看到任何不友好的错误信息 5 1.3.1 说明 5 1.3.2 应对 5 1.3.3 举例 5 二、PHP编码安全 6 2.1 POST/GET参数传值/字符串输入/数据入库等严格的危险字符过滤处理 6 2.1.1 说明 6 2.2.2 应对 6 2.2.3 举例 6 2.2 相关PHP的I/O操作,需要注意限制权限,文件名或目录名或内容都要做好过滤处理 8 2.2.1 说明 8 2.2.2 应对 8 2.2.3 举例 8 2.3 敏感信息(如PASSWORD/银行帐号等)不要依赖COOKIE,SESSION,最好读表,并尽量缓存读表数据 8 2.3.1 说明 8 2.3.2 应对 9 2.3.3 举例 9 2.4 注意对网站根目录及下面所有子目录及文件的权限控制与保护,不要让配置文件/系统信息等文件暴露 10 2.4.1 说明 10 2.4.2 应对 10 2.4.3 举例 10 2.5 屏蔽或定制化出错信息 10 2.5.1 说明 10 2.5.2 应对 11 2.5.3 举例 11 2.6 数据库的读取等操作、POST/GET传值需要做频率限制与Token校验 11 2.6.1 说明 11 2.6.2 应对 11 2.6.3 举例 11 2.7 有类似文件下载/或文本流下载等功能的,尽量避免使用URL直接调用目标文件地址的方式 12 2.7.1 说明 12 2.7.2 应对 12 2.7.3 举例 12 2.8 MYSQL 的用户最好分开,不要用ROOT用户来连接MYSQL 13 2.8.1 说明 13 2.8.2 应对 13 2.8.3 举例 13 3 参考内容 13
java,c/c++,php,c#安全编码规范,从代码层面避免被入侵 1 业务安全编码规范 6 1.1 输入验证和数据合法性校验 6 1.1.1 避免SQL注入 6 1.1.2 避免XML注入 6 1.1.3 避免跨站点脚本(XSS) 7 1.1.4 避免跨站请求伪造(CSRF) 8 1.1.5 避免敏感信息泄露 12 1.2 安全框架 12 1.2.1 Apache Shiro安全框架 12 1.2.2 webSecrity安全框架 13 1.2.3 Enterprise Security API 13 2 基础安全编码规范 15 2.1 声明和初始化 15 2.1.1 避免类初始化的相互依赖 15 2.2 表达式 16 2.2.1 不可忽略方法的返回值 16 2.2.2 不要引用空指针 16 2.2.3 使用Arrays.equals()来比较数组的内容 16 2.3 数字类型和操作 17 2.3.1 防止整数溢出 17 2.3.2 避免除法和取模运算分母为零 18 2.4 类和方法操作 18 2.4.1 数据成员声明为私有,提供可访问的包装方法 18 2.4.2 敏感类不允许复制 18 2.4.3 比较类的正确做法 19 2.4.4 不要硬编码敏感信息 19 2.4.5 验证方法参数 19 2.4.6 不要使用过时、陈旧或低效的方法 20 2.4.7 数组引用问题 20 2.4.8 不要产生内存泄露 20 2.5 异常处理 21 2.5.1 不要忽略捕获的异常 21 2.5.2 不允许暴露异常的敏感信息 21 2.5.3 不允许抛出RuntimeException, Exception,Throwable 22 2.6 多线程编程 23 2.6.1 确保共享变量的可见性 23 2.6.2 确保共享变量的操作是原子的 24 2.6.3 不要调用Thread.run(),不要使用Thread.stop()以终止线程 26 2.6.4 确保执行阻塞操作的线程可以终止 26 2.6.5 相互依存的任务不要在一个有限的线程池执行 27 2.7 输入输出 27 2.7.1 程序终止前删除临时文件 27 2.7.2 检测和处理文件相关的错误 27 2.7.3 及时释放资源 27 2.8 序列化 28 2.8.1 不要序列化未加密的敏感数据 28 2.8.2 在序列化过程中避免内存和资源泄漏 29 3 其他参考资料 30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值