PHP安全开发规范

#### 一.目的


《PHP安全开发规范》是本信息系统安全标准的一部分,主要目的是根据信息安全管理政策的要求,为我司的PHP开发的设计、实施及维护的技术和安全参考依据。

#### 二.范围

安全标准所有条款默认适用于所有PHP开发程序,某些特殊的会明确指定适用范围。

#### 三.内容

##### 3.1 Cookie使用原则

3.1.1 禁止在Cookie中记录机密信息,如用户密码,信用卡号,银行卡号等,需要保密或者业务逻辑相关的数据需要加密或签名保存
3.1.2 和登录认证相关的Cookie必须设置httponly属性为true
3.1.3 只在https环境下传递的Cookie需要设置secure属性为true(ssl)

##### 3.2 Header输出原则

原则上,所有的header输出都要符合标准

3.2.1 Content-Type的设置原则
一般情况下,各种数据都有自己的类型,例如输入json格式的文件是,应指定Content-Type为 application/json
输出js的时候,应该指定Content-Type为 application/javascript 。 禁止不设置Content-Type,或者默认指定为 text/html

3.2.2 如果未指定Content-Type,则应指定

X-Content-Type-Options:nosniff

##### 3.3 跨漏洞脚本攻击(简称:XSS)

3.3.1 跨站脚本攻击就是指恶意攻击者向网页中插入一段恶意代码,当用户浏览该网页时,嵌入到网页中的恶意代码就会被执行。
跨站脚本攻击漏洞,英文名称Cross Site Scripting,简称CSS又叫XSS。它指的是恶意攻击者向Web页面中插入一段恶意代码,当用户浏览该页面时,嵌入到Web页面中的恶意代码就会被执行,从而达到恶意攻击者的特殊目的.

危害:

1.)恶意用户可以使用该漏洞来盗取用户账户信息、模拟其他用户身份登录,更甚至可以修改网页呈现给其他用户的内容。

2.)恶意用户可以使用JavaScript、VBScript、ActiveX、HTML语言甚至Flash应用的漏洞来进行攻击,从而来达到获取其他的用户信息目的。

漏洞代码示例:
$var=$_GET['a'];
echo $var;
?>


漏洞修复示例:
$var=Htmlspecialchars($_GET['a'],ENT_QUOTES);
echo $var;
?>

解决方案:
1.)使用Htmlspecialchars($outputString,ENT_QUOTES)对危险变量过滤输出.
2.)建议过滤所有用户输入的数据,切记一切来源用户输入的数据都不是安全的。

##### 3.4 跨站点请求伪造(简称:CSRF)

通过伪装来自受信任用户的请求来利用受信任的网站。 标准实现方式:
1.)第一次请求页面时,服务器issue cookie并在页面中带上一个hidden项,cookie的值和hidden项的值相同.
2.)该值通过session cookie+服务器端私钥做md5生成,取生成的md5值作为验证依据.
3.) 服务器端必须做验证 ,生成和验证都需要由服务器端完成。
##### 3.5 SQL注入

1.)SQL注入攻击就是攻击者通过欺骗数据库服务器执行非授权的任意查询过程。
2.)SQL注入攻击就其本质而言,它利用的工具是SQL的语法,针对的是应用程序开发者在编程过程中的漏洞,“当攻击者能够操作数据,向应用程序中插入一些SQL语句时,SQL注入攻击就发生了”。实际上,SQL注入攻击是攻击者通过在应用程序中预先定义好的查询语句结尾加上额外的SQL语句元素,欺骗数据库服务器执行非授权的任意查询。SQL注入漏洞是目前互联网最常见也是影响非常广泛的漏洞。
危害:
被SQL注入后可能导致以下后果:
1.)网页被篡改
2.)数据被篡改
3.)核心数据被窃取
4.)数据库所在服务器被攻击攻陷.
漏洞代码示例
$id=$_GET['id'];
$conn = mysql_connect("localhost","root","") or die ("wrong!");
$sel=mysql_select_db("mydb",$conn);
$sql="select * from user where id = ".id
$que=mysql_query($sql,$conn);
?>
漏洞修复示例:
$id=$_GET['id'];
$conn = mysql_connect("localhost","root","") or die ("wrong!");
$sel=mysql_select_db("mydb",$conn);
$sql="select * from user where id = :id"
$stmt = $conn->prepare($sql);
$stmt->execute(array(':id'=>$id));
?>
解决方案:
1.)PHP5请使用PDO方式进行绑定,使用PDO,PHP的PDO文档:
2.)在web代码中需要对用户输入的数据进行严格过滤。

##### 3.6 文件包含漏洞

1.)文件包含漏洞允许通过特殊的指令将脚本源码文件的内容合并至当前的文件中执行。
2.)很多脚本语言允许通过特殊的指令(如PHP 通过require关键字)将其他脚本源码文件的内容合并至当前的文件中执行,如果这些特殊的指令在包含的文件路径中含有用户提交的数据,则恶意攻击者就有可能通过构造特殊的数据将WEB服务器限制访问的文件内容(如操作系统或某些重要应用的配置文件)包含进来并通过浏览器获取其内容,这种方式通常称为本地文件包含;如果应用程序的配置还允许包含远程的其他服务器上的文件,恶意攻击者就有可能构造特殊的脚本然后通过包含并予以执行,进而获取WEB应用的敏感数据或控制权。
危害: 恶意攻击者可以通过文件包含漏洞获取敏感文件的内容或直接执行其指定的恶意脚本,进而获取对WEB应用本身的完全控制。 漏洞示例代码:
//x.php?dir=../../../../../../etc/passwd%00
$dir = $_GET['dir'];
if(!$dir) $dir = './';
require_once($dir.'/safe.php');
?>
漏洞修复示例:
$dir = $_GET['dir'];
if(!$dir) $dir = './';
require_once(basename($dir).'/safe.php');
?>
解决方案:
1.) PHP配置安全项:allow_url_fopen = Off 、allow_url_include = Off
2.)代码安全:使用常量调用文件包含函数require、include、require_once、include_once,不要使用变量作为参数调用这个四个函数。

##### 3.7 命令注入漏洞

命令注入是指由于服务端代码漏洞导致恶意用户输入在服务端被执行命令,是一种高危安全漏洞。 危害: 利用该漏洞,可以在服务器上执行攻击者拼装的代码。
代码漏洞示例
$myvar = "varname";
$x = $_GET['arg'];
eval("\$myvar = \$x;");
?>
代码漏洞修复:
$myvar = "varname";
$x = $_GET['arg'];
$myvar = $x;
?>
修复方案:
1.)严格检查控制程序的参数。

##### 3.8 命令执行漏洞

命令执行漏洞是指应用程序对传入命令行的参数过滤不严导致恶意用户能控制最终执行的命令,进而入侵系统,导致严重破坏的高危漏洞。\\
危害: 利用漏洞,可以在服务器上执行任意系统命令。
漏洞代码示例
$myvar = "varname";
$x = $_GET['arg'];
// 默认通过url传入ls -al 进行执行
system($x);
?>
PHP修复示例
$myvar = "varname";
$x = $_GET['arg'];
// 默认通过url传入ls -al 进行执行
if($x=='/bin/ls -al'){
system('/bin/ls -al');
}else{
return;
}
?>
修复方案:
1.)对代码中可执行的特殊函数入口严格过滤,严格控制system(),eval(),exec()等函数的调用。
2.)在PHP代码中禁止外部可控参数传入到该类可执行命令函数中.

##### 3.9 文件上传漏洞

允许用户上传任意文件可能会让攻击者注入危险内容或恶意代码,并在服务器上运行。
漏洞代码示例:
if(isset($_POST["form"]))
{
$uploadfile = "upfiles/".$_FILES['upfile']['name'];
move_uploaded_file($_FILES['upfile']['tmp_name'], $uploadfile);
//没有检查文件类型就直接上传
print_r($_FILES);
die();
}
?>
修复方案:
1.)上传文件后缀进行白名单检验。
2.)上传文件内容进行合法性检查。
3.)上传文件自动重命名。

##### 3.10 HTTP头部注射拆分漏洞:

HTTP响应拆分漏洞,也叫CRLF注入攻击。CR、LF分别对应回车、换行字符。HTTP头由很多被CRLF组合分离的行构成,每行的结构都是“键:值”。如果用户输入的值部分注入了CRLF字符,它有可能改变的HTTP报头结构。
危害: HTTP响应拆分是一个新的应用程序的攻击技术,使网页缓存中毒,跨用户涂改,如各种新的攻击,劫持用户的敏感信息和跨站点脚本(XSS)的网页.
漏洞代码示例:
$location = $_GET['some_location'];
header("location: $location");
?>

假设在请求中提交了一个由标准的字母和数字字符组成的字符串,如 "index.html",那么包含此 cookie 的 HTTP 响应可能表现为以下形式:
HTTP/1.1 200 OK
...
location: index.html
...
然而,因为该位置的值由未经验证的用户输入组成,所以仅当提交给 some_location 的值不包含任何 CR 和 LF 字符时,响应才会保留这种形式。
如果攻击者提交的是一个恶意字符串,比如 :
"index.html\r\nHTTP/1.1 200 OK\r\n...",
那么此 HTTP 响应就会被分割成以下形式的两个响应:
HTTP/1.1 200 OK
location: index.html
HTTP/1.1 200 OK
...
显然,第二个响应已完全由攻击者控制,攻击者可以用所需的头文件和正文内容构建该响应。攻击者可以构建任意 HTTP 响应,从而发起多种形式的攻击
解决方案:
1.)限制用户输入的CR和LF,或者对CR和LF字符正确编码后再输出,以防止注入自定义HTTP头。
2.)严格检查变量是否已经初始化,禁止header()函数中的参数外部可控。

##### 3.11 URL跳转漏洞

网站存在任意网址跳转漏洞,恶意攻击者可以通过该漏洞,将用户访问的目标网站跳转到其它网站
危害: 该漏洞可能导致网站用户被钓鱼,造成不必要的损失,严重影响网站在用户中的形像!
漏洞示例: http://api.immomo.com/?u=http://www.baidu.com 存在漏洞,可以跳转到攻击者的钓鱼页面,那么需要对参数 u 的值做白名单限制,只能跳转到白名单内允许的域名.
解决方案: 限制参数不允许向外域跳转,进行白名单限制.

##### 3.12 其它

所有的账号登陆域,都应该设置相应的CSP选项,防止跨域ifranme或者是xss