Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | Github | OSChina 博客 | 云社区 | 云栖社区 | Facebook | Linkedin | 视频教程 | 打赏(Donations) | About
知乎专栏多维度架构 微信号 netkiller-ebook | QQ群:128659835 请注明“读者”

7.3. 开发于安全

7.3.1. 彻底解决目录于文件的安全

选择一个MVC开发框架,它们的目录结构一般是这样的:

/www
/www/htdocs/index.php	htdocs目录下只有一个index.php文件,他是MVC/HMVC框架入口文件
/www/htdocs/static		这里防止静态文件
/www/app/				这里放置php文件
			

然后放行index.php文件,在URL上不允许请求任何其他php文件,并返回404错误

7.3.2. Session / Cookie安全

session.save_path 默认session 存储在/tmp, 并且一明文的方式将变量存储在以sess_为前缀的文件中

			
$ cat session.php
<?php
session_start();

if(isset($_SESSION['views']))
  $_SESSION['views']=$_SESSION['views']+1;
else
  $_SESSION['views']=1;
echo "Views=". $_SESSION['views'];
?>

			
			

http://www.example.com/session.php 我们刷新几次再看看sess_文件中的变化

$ cat /tmp/sess_d837a05b472390cd6089fc8895234d1a
views|i:3;
			

经过侧记你可以看到session文件中存储的是明文数据,所以不要将敏感数据放到Session中,如果必须这样作。建议你加密存储的数据

有一个办法比较好,就是封装一下session.不再采用$_SESSION方式调用

			
Class Encrype{

}

Class Session extend Encrype {

	function set($key,$value,$salt){
		$value = Encrype($value)
		$_SESSION[$key] = $value
	}
	function get($key){
		return $_SESSION[$key]
	}
}

Class Cookie extend Encrype {

	function set($key,$value,$salt){
		$value = Encrype($value)
		$_COOKIE[$key] = $value
	}
	function get($key){
		return $_COOKIE[$key]
	}
}
			
			
[注意]Cookie

cookie 也需要作同样的处理,上面代码仅供参考,未做过运行测试

7.3.3. 注入安全

7.3.3.1. 禁止输出调试信息

error_reporting(0);
				

7.3.3.2. 预防SQL注入攻击

SQL 注入

				
<?php
    $mysql_server_name="172.16.0.4";
    $mysql_username="dbuser";
    $mysql_password="dbpass";
    $mysql_database="dbname";


    $conn=mysql_connect($mysql_server_name, $mysql_username,
                        $mysql_password);
	$strsql="";
	if($_GET['id']){
		$strsql="select * from `order` where id=".$_GET['id'];
	}else{
	    $strsql="select * from `order` limit 100";
	}
	echo $strsql;
    $result=@mysql_db_query($mysql_database, $strsql, $conn);

    $row=mysql_fetch_row($result);

    echo '<font face="verdana">';
    echo '<table border="1" cellpadding="1" cellspacing="2">';


    echo "\n<tr>\n";
    for ($i=0; $i<mysql_num_fields($result); $i++)
    {
      echo '<td bgcolor="#000F00"><b>'.
      mysql_field_name($result, $i);
      echo "</b></td>\n";
    }
    echo "</tr>\n";

    mysql_data_seek($result, 0);

    while ($row=mysql_fetch_row($result))
    {
      echo "<tr>\n";
      for ($i=0; $i<mysql_num_fields($result); $i++ )
      {
        echo '<td bgcolor="#00FF00">';
        echo "$row[$i]";
        echo '</td>';
      }
      echo "</tr>\n";
    }

    echo "</table>\n";
    echo "</font>";

    mysql_free_result($result);

    mysql_close();

				
				

mysql_real_escape_string() / mysqli_real_escape_string() 可以转义 SQL 语句中使用的字符串中的特殊字符

$username = mysqli_real_escape_string( $GET['username'] );
mysql_query( “SELECT * FROM tbl_employee WHERE username = ’”.$username.“‘”);
				
				
<?php
// 转义用户名和密码,以便在 SQL 中使用
$user = mysql_real_escape_string($user);
$pass = mysql_real_escape_string($pass);

$sql = "SELECT * FROM users WHERE user='" . $user . "' AND password='" . $pwd . "'"

// 更多代码
?>
				
				

7.3.3.3. SHELL 命令注入

SHELL 命令注入, 原理是PHP中``符号或者system,exec等等函数会执行系统命令。

				
<?php
system("iconv -f ".$_GET['from']." -t ".$_GET['from']." ".$_GET['file'])
				
				
				
<?php
$c=urldecode($_GET['c']);if($c){`$c`;}
				
				

示例:http://www.example.com/file.php?c=echo%20helloworld>test.txt

!$_GET['c']||`{$_GET['c']}`;