web 安全与性能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rorntuck7/article/details/84615538

Apache

Apache 案例
Apache : root
Apache 子进程 : nobody
HTDOCS 目录 : /var/www

/var/www
|--include
|--image
|--temp
|--...

很多人会将/var/www用户与组设置为 nobody:nogroup / nobody:nobody, 同时因为images会上传文件需要设置777, 很多书本于教程上面也是这样讲的, 这样配置会有什么问题呢?我们来分析一下:

我们假设,一个用户上传一个文件到images目录,会有几种情况:

上传一个.php文件,我们可以通过程序禁止上传.php文件

我们上传一个.jpg文件,OK 通过了,通过某种手段将他重命名位.php扩展名的文件,然后通过http://www.example.com/images/your.php 运行它,your.php 可以做什么呢? 它可以查看所有文件,修改所有文件,创建其他php文件,去你可include目录下看config.php然后下载数据库。

内部开发人员偷偷将一个程序植入到系统中,这个做code review 可以避免

如何避免这样问题出现,有一个办法,我们新建一个用户www, webserver 进程是nobody,程序目录/var/www中的代码是www用户,nobody可能读取但不能修改。/var/www/images 目录所有者是nobody可以上传图片

chown www /var/www/
chown nobody /var/www/images
find /var/www/ -type d -exec chmod 555 {} \;
find /var/www/ -type f -exec chmod 444 {} \;
chmod 755 /var/www/images

使所有可能目录允许运行.php文件,http://www.example.com/images/your.php 将被拒绝. include 也是同样处理方式,只允许使用include_once,require_one 包含,不允许http://www.example.com/include/your.php运行

<Location ~ "/((js/)|(css/)|(images/)).*\.php">
    Order Deny,Allow
    Deny from all
</Location>

<Location /includes/>
        Order allow,deny
        Deny from all
</Location>
<Location /library/>
        Order allow,deny
        Deny from all
</Location>

<Directory /var/www/themes/>
    <Files *.php>
        Order allow,deny
        Deny from all
    </Files>
</Directory>

Nginx / lighttpd + fastcgi

fastcgi 遇到的问题与上面apache案例中遇到的问题类似,不同是的fastcgi把动态于静态完全分开了,这样更容易管理,我们可以这样入手
nginx / lighttpd : root
web server 子进程 : nobody
php-fpm : root
php-fpm 子进程 : www

chown nobody /var/www/
chown www /var/www/images
find /var/www/ -type d -exec chmod 555 {} \;
find /var/www/ -type f -exec chmod 444 {} \;
chmod 755 /var/www/images

/var/www所有权限给nobody, images权限给www, 同时保证www用户可以读取/var/www下的程序文件

location ~ ^/upload/.*\.php$
{
        deny all;
}

location ~ ^/static/images/.*\.php$
{
        deny all;
}

location ~ /include/.*\.php$ {
    deny all;
}

location ~ .*\.(sqlite|sq3)$ {
    deny all;
}
vim /etc/php7/fpm/pool.d/www.conf

user = www
group = www


chdir = /
改为
chdir = /var/www


chroot = /var/www
这样当用户试图通过chdir跳转到/var/www以外的目录是,将被拒绝

web server 版本信息

Apache:
ServerTokens ProductOnly
ServerSignature Off

Nginx:
server_tokens off;

php_flag / php_admin_flag

你在php.ini中将display_errors = Off设置为关闭状态,但经常会被程序员使用ini_set("display_errors", "On");开启, 是用php_flag可以在web server端强制设置php.ini参数

php_flag register_globals off
php_flag magic_quotes_gpc off

php_admin_value(php_admin_flag) 与 php_value(php_flag) 有何不同?

不同的地方是:php_admin_value(php_admin_flag) 命令只能用在apache的httpd.conf文件中, 而php_value(php_flag)则是用在.htacces

在.htaccess中停用全局变量

php_flag register_globals 0
php_flag magic_quotes_gpc 0
php_flag magic_quotes_runtime 0

服务器防止URL注入

if ($request_uri ~* (.*)(insert|select|delete|update|count|concat|cost|union|drop|table|*|%|master|truncate|declare|'|;|and|or|(|)|exec)(.*)$ ) 
{ 
    return 403; 
}
if ( $query_string ~* ".*[;'<>].*" ){
    return 403;
}

php.ini

1.危险PHP函数

这些函数应该尽量避免使用它们

exec, system, ini_alter, readlink, symlink, leak, proc_open, popepassthru, chroot, scandir, chgrp, chown, escapeshellcmd, escapeshellarg, shell_exec, proc_get_status, max_execution_time, opendir,readdir, chdir ,dir, unlink,delete,copy,rename
对于后门植入主要是用下面几个方法

eval, gzinflate, str_rot13, base64_decode
针对目录与文件的函数

disable_functions=chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir,rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown

针对 php.ini 操作的函数
ini_set,

2.隐藏PHP版本信息

expose_php Off

3.session名字可以泄露你的服务器采用php技术

session.name = PHPSESSID
伪装成Tomcat
session.name = JSESSIONID

4. 隐藏PHP出错信息

display_errors = Off
同时开启error_log日志
error_log = php_errors.log

5.open_basedir 防止操作web环境意外文件目录

open_basedir = /www/:/tmp/

如果要设置多个目录,window使用;分隔目录,Linux使用:分隔目录。 

开发于安全

1.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]
    }
}

上面代码仅供参考,未做过运行测试

注入安全

1.禁止输出调试信息

error_reporting(0);

2. 预防SQL注入攻击
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 . "'"

// 更多代码
?>

3.SHELL 命令注入

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

1、尽量不要执行外部命令

2、使用自定义函数或函数库来替代外部命令的功能

3、使用escapeshellarg函数来处理命令参数

4、使用safe_mode_exec_dir指定可执行文件的路径

esacpeshellarg函数会将任何引起参数或命令结束的字符转义,单引号“’”,替换成“\’”,双引号“"”,替换成“\"”,分号“;”替换成“\;”

用safe_mode_exec_dir指定可执行文件的路径,可以把会使用的命令提前放入此路径内

safe_mode = On

safe_mode_exec_dir = /usr/local/php/bin/

执行效率

如果是web应用程序,通常我们必须将执行时间控制在30秒以内, 10秒最佳. 否则用户是没有耐心等待你的网站打开.

1.timeout

下面的流程展示了从用户打开浏览器到页面展示出来的整个流程, 每个流程都可能出现 timeout

user -> dns -> web server -> app server -> cache -> database

严格限制运行时间

外部引用域名必须写入hosts文件, 防止解析时间过长

必须设置严格的超时策略, 方式程序长时间等待不退出, 占用系统资源

<?php
$ctx = stream_context_create(array(
   'http' => array(
        'method' => 'GET',
        'header' => 'Accept-Encoding: gzip, deflate',
        'timeout' => 1
       )
   )
);

$html = file_get_contents("http://www.163.com/", false, $ctx);
echo strlen($html);
?>

2.mysql

show variables like '%timeout%'

3.浏览器上传文件尺寸控制

Nginx

client_max_body_size 8M

设置不能过大,因为可以通过你的网站上传功能,持续上传实现攻击。

猜你喜欢

转载自blog.csdn.net/rorntuck7/article/details/84615538