PHP安全 [安全编码]
Posted 王小帥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP安全 [安全编码]相关的知识,希望对你有一定的参考价值。
目录
文件系统安全
源码:
<?php
//从用户目录中删除指定的文件
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$userfille";
unlink ("$homedir/$userfile");
echo "The file has been deleted!";
?>
如果攻击者恶意构造如下:
user_submitted_name="../etc"
user_submitted_filename="passwd"
因为源码是直接拼接的,所以上述执行会直接把/etc/passwd文件执行删除操作。(属于越权行为)
安全编码:
- 不允许用户有拼接权限。
- 对用户输入进行完整的校验。
校验源码(白名单):
<?php
$username = $_SERVER('REMOTE_USER'); //使用认证机制
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if(!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\\.(?!\\.))+$/iD',userfile)){
die("Bad username/filename");
}
...
?>
ctype_alnum():做字母和数字字符检测
( : ? 非捕获分组,仅仅匹配
( ? ! \\. ) 匹配非.的内容
分析:
- ../etc 在上述正则会导致die,即 ..开头的文件不允许
- /符号会导致die。
- 根据操作系统的不同,存在着各种各样需要注意的文件,包括联系到系统的设备( /dev/或者COM1)、配置文件(/ect/文件和.ini文件)、常用的存储区域(/home/ 或者My Documents )等等。由于此原因,建立一个策略禁止所有权限而只开放明确允许的通常更容易些。
数据库安全(SQL注入)
恶意输入:
尽量避免直接的数据库查询语句的拼接,无论数据库种类。
<?php
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
?>
a%' exec master..xp_cmdshell 'net user test testpass /ADD'
<?php
$query = "SELECT * FROM products WHERE id LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);
?>
错误输出:
尽量避免直接输出原本的数据库错误信息,而自行构造。
<?php
$sql = "SELECT * FROM movies WHERE title LIKE '%" . sqli($title) . "%'";
$recordset = mysql_query($sql,$link);
if(!$recordset)
{
die("ERROR!");
}
}
在使用数据库时候,对于敏感信息加密存储:
- md5($pass)
- md5($salt.md5($pass))
- SHA-1
- SHA-2(SHA-224,SHA-256,SHA-384和SHA-512)
- 推荐使用:
- md5($salt.md5($pass))与SHA-256
命令执行
源码:
$targetUrl = $_POST["target"];
switch ($targetUrl) {
case "www.target.com": echo "" . shell_exec("nslookup www.target.com");
break;
case "web.target.com": echo "" . shell_exec("nslookup web.target.com");
break;
...
default:echo "" . shell_exec("nslookup www.target.com");
}
}
如果命令执行不可缺少,使用白名单的形式,并且硬编码禁止拼接。
XSS
<?php
//用户可控数据不需存储直接响应的,应编码输出。
echo $this->securityUtil->encodeForhtml($data);
echo $this->securityUtil->encodeForjavascript($data);
//用户可控数据需存储响应,应过滤字符。
$this->securityUtil->purifier($_GET["data"]);
}
注释
资源泄露
<?php
$file = fopen("temp.txt","w") or die ("Unable to open file!");
fclose($file);
本地文件包含
<?php
$filename = $_GET["filename"];
switch ($filename){
case "file.txt":include("./file.txt");
break;
default:include("./readme.txt");
}
当必须要接受外部文件名的时候,同样是白名单。
任意文件上传
<?php
$config = array('limit'=>5 * 1024 *1024, //允许上传的文件最大大小
'type'=>array( //允许的上传文件后缀及MIME
"gif"=>"image/gif",
"jpg"=>"image/jpeg",
"png"=>"image/png")
);
$title = $_FILES["file"];
$data = $this->securityUtil->verifyUploadFile($file,$config);
if($data['flag']!=true){
returun; //上传失败
}
对文件的大小,后缀名以及MIME进行验证。对上传的路径,文件名以及它的权限进行限制,甚至对文件内容进行验证。
安全编码细则:
- 所有输入的数据都是有害的(直接或者间接由用户输入的)
- 不依赖运行环境的安全配置
- 安全控制措施落实在最后执行阶段
- 最小化
- 失败终止
总则:
绝对安全的系统是不存在的。最好的安全机制应该能在不防碍用户,并且不过多地增加开发难度的情况下做到能满足需求。
以上是关于PHP安全 [安全编码]的主要内容,如果未能解决你的问题,请参考以下文章