1. 程式人生 > >PHP 安全與效能

PHP 安全與效能

1. Apache mod_php / php-fpm

目錄許可權安全

1.1. 使用者許可權

web server 啟動使用者不能於執行使用者為同一個使用者

web server 執行使用者與php程式不能為同一個使用者

root      1082  0.0  0.1  11484  2236 ?        Ss   Mar01   0:00 nginx: master process /usr/sbin/nginx
www-data 13650  0.0  0.0  11624  1648 ?        S    09:44   0:00 nginx: worker process
www-data 13651  0.0  0.0  11624  1132 ?        S    09:44   0:00 nginx: worker process
www-data 13652  0.0  0.0  11624  1132 ?        S    09:44   0:00 nginx: worker process
www-data 13653  0.0  0.0  11624  1132 ?        S    09:44   0:00 nginx: worker process
			
  1. 父程序

    root 啟動 web server, 此時web server 父程序應該是 root,同時父程序監聽80埠

  2. 子程序

    父程序派生許多子程序,同時使用setuid,setgid將子程序許可權切換為非root

    子程序使用者可以通過httpd.conf設定

    User nobody
    Group nobody
    					

    nginx.conf

    $ cat /etc/nginx/nginx.conf
    user www-data;
    					
  3. fastcgi 程序

    root     13082  0.0  0.1  19880  2584 ?        Ss   09:28   0:00 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)
    www-data 13083  0.0  0.1  20168  3612 ?        S    09:28   0:00 php-fpm: pool www
    www-data 13084  0.0  0.1  20168  2808 ?        S    09:28   0:00 php-fpm: pool www
    www-data 13085  0.0  0.1  20168  2812 ?        S    09:28   0:00 php-fpm: pool www
    www-data 13086  0.0  0.1  20168  2812 ?        S    09:28   0:00 php-fpm: pool www
    					

    php-fpm 於apache類似,都是root父程序,然後派生子程序,由於fastcgi 使用 9000 所有我們可以不使用root啟動php-fpm

現在我們開始講解安全配置問題

我們目的是避免使用者通過漏洞提升許可權,或者由於許可權配置不當產生漏洞

1.1.1. Apache

Apache 案例

  1. Apache : root

  2. Apache 子程序 : nobody

  3. HTDOCS 目錄 : /var/www

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

很多人會將/var/www使用者與組設定為 nobody:nogroup / nobody:nobody, 同時因為images會上傳檔案需要設定777, 很多書本於教程上面也是這樣講的, 這樣配置會有什麼問題呢?我們來分析一下:

我們假設,一個使用者上傳一個檔案到images目錄,會有幾種情況:

  1. 上傳一個.php檔案,我們可以通過程式禁止上傳.php檔案

  2. 我們上傳一個.jpg檔案,OK 通過了,通過某種手段將他重新命名位.php副檔名的檔案,然後通過http://www.example.com/images/your.php 執行它,your.php 可以做什麼呢? 它可以檢視所有檔案,修改所有檔案,建立其他php檔案,去你可include目錄下看config.php然後下載資料庫。

  3. 內部開發人員偷偷將一個程式植入到系統中,這個做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>
				
				

1.1.2. Nginx / lighttpd + fastcgi

Nginx / lighttpd 案例分析

  1. nginx / lighttpd : root

  2. web server 子程序 : nobody

  3. php-fpm : root

  4. php-fpm 子程序 : nobody

  5. HTDOCS 目錄 : /var/www

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

fastcgi 遇到的問題與上面apache案例中遇到的問題類似,不同是的fastcgi把動態於靜態完全分開了,這樣更容易管理,我們可以這樣入手

  1. nginx / lighttpd : root

  2. web server 子程序 : nobody

  3. php-fpm : root

  4. 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/php5/fpm/pool.d/www.conf

user = www
group = www
				

/etc/php5/fpm/pool.d/www.conf

chdir = /
改為
chdir = /var/www
				

chroot可以徹底解決cd跳轉問題,單配置比較繁瑣

chroot = /var/www
				

這樣當用戶試圖通過chdir跳轉到/var/www以外的目錄是,將被拒絕

1.2. web server 版本資訊

Apache:
ServerTokens ProductOnly
ServerSignature Off

Nginx:
server_tokens off;
			

1.3. 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
			

2. php.ini

2.1. Magic quotes

限於5.2。x 版本

magic_quotes_gpc = On
magic_quotes_runtime = On
			

測試程式

			
<form action="" method="post" >
STR:<input type="text" name="str">
<input type="submit">
</form>
<?php

if (get_magic_quotes_gpc()) {
	$str = $_POST['str'];
	echo '這裡是get_magic_quotes_gpc()轉義過後的:' ,$str, '<hr />';
} else {
	$str = addslashes($_POST['str']);
	echo '現在通過addslashes傳遞過來的值是:' ,$_POST['str'], '<br>';
}


function stringFilter($str)
{
	if (ini_get('magic_quotes_gpc)') {
		return $str;
	} else {
		return addslashes($str);
	}
}
			
			

2.2. 危險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.2.1. chdir()函式安全演示

				
$ cat chdir.php
<pre>
<?php
echo "current:".getcwd();
echo '<br />';
chdir('/');
echo "chdir:".getcwd();
echo '<br />';
$lines = file('etc/passwd');

foreach ($lines as $line_num => $line) {
    echo "Line #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br />\n";
}
?>
</pre>

				
				

執行結果

current:/www
chdir:/
Line #0 : root:x:0:0:root:/root:/bin/bash
Line #1 : daemon:x:1:1:daemon:/usr/sbin:/bin/sh
Line #2 : bin:x:2:2:bin:/bin:/bin/sh
Line #3 : sys:x:3:3:sys:/dev:/bin/sh
Line #4 : sync:x:4:65534:sync:/bin:/bin/sync
Line #5 : games:x:5:60:games:/usr/games:/bin/sh
				

2.3. 隱藏PHP版本資訊

expose_php Off
			

2.4. session名字可以洩露你的伺服器採用php技術

session.name = PHPSESSID
			

偽裝成Tomcat

session.name = JSESSIONID
			

2.5. 隱藏PHP出錯資訊

display_errors = Off
			
同時開啟error_log日誌
error_log = php_errors.log
			

2.6. open_basedir 防止操作web環境意外檔案目錄

			
open_basedir = /www/:/tmp/
			
			

測試指令碼

			
<?php
chdir('/etc');

printf(file('/etc/fstab'));
			
			

實際效果

			
Warning: chdir(): open_basedir restriction in effect. File(/etc) is not within the allowed path(s): (/www/:/tmp/) in /www/index.php on line 2

Warning: file(): open_basedir restriction in effect. File(/etc/fstab) is not within the allowed path(s): (/www/:/tmp/) in /www/index.php on line 2

Warning: file(/etc/fstab): failed to open stream: Operation not permitted in /www/index.php on line 2
			
			

3. 開發於安全

3.1. 徹底解決目錄於檔案的安全

選擇一個MVC開發框架,它們的目錄結構一般是這樣的:

/www
/www/htdocs/index.php	htdocs目錄下只有一個index.php檔案,他是MVC/HMVC框架入口檔案
/www/htdocs/static		這裡防止靜態檔案
/www/app/				這裡放置php檔案
			

然後放行index.php檔案,在URL上不允許請求任何其他php檔案,並返回404錯誤

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 也需要作同樣的處理,上面程式碼僅供參考,未做過執行測試

3.3. 注入安全

3.3.1. 禁止輸出除錯資訊

error_reporting(0);
				

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;
    [email protected]_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 . "'"

// 更多程式碼
?>
				
				

3.3.3. SHELL 命令注入

SHELL 命令注入

				
<?php
system("iconv -f ".$_GET['from']." -t ".$_GET['from']." ".$_GET['file'])
				
				

4. 執行效率

如果是web應用程式,通常我們必須將執行時間控制在30秒以內, 10秒最佳. 否則使用者是沒有耐心等待你的網站開啟.

4.1. timeout

下面的流程展示了從使用者開啟瀏覽器到頁面展示出來的整個流程, 每個流程都可能出現 timeout

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

			
嚴格限制執行時間

外部引用域名必須寫入hosts檔案, 防止解析時間過長

必須設定嚴格的超時策略, 方式程式長時間等待不退出, 佔用系統資源

			
<?php
$ctx = stream_context_create(array(
   'http' => array(
       'timeout' => 1 //設定一個超時時間,單位為秒
       )
   )
);
file_get_contents("http://example.com/file.ext", false, $ctx);
?>



<?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);
?>
			
			

4.1.1. mysql

show variables like '%timeout%'
				

相關推薦

PHP 安全效能

1. Apache mod_php / php-fpm 目錄許可權安全 1.1. 使用者許可權 web server 啟動使用者不能於執行使用者為同一個使用者 web server 執行使用者與php程式不能為同一個使用者 root 1082 0.0

Python--Redis實戰:第四章:資料安全效能保障:第7節:非事務型流水線

之前章節首次介紹multi和exec的時候討論過它們的”事務“性質:被multi和exec包裹的命令在執行時不會被其他客戶端打擾。而使用事務的其中一個好處就是底層的客戶端會通過使用流水線來提高事務執行的效能。本節將介紹如何在不使用事務的情況下,通過使用流水線來進一步提升命令的執行效能。 之前章節曾經介紹過一

web 安全效能

Apache Apache 案例 Apache : root Apache 子程序 : nobody HTDOCS 目錄 : /var/www /var/www |--include |--image |--temp |--... 很多人會將/var/www使用者與組設定為 nobo

Python--Redis實戰:第四章:資料安全效能保障:第8節:關於效能方面的注意事項

習慣了關係資料庫的使用者在剛開始使用Redis的時候,通常會因為Redis帶來的上百倍的效能提升而感到欣喜若狂,卻沒有認識到Redis效能實際上還可以進一步的提高。雖然上一節介紹的非事務型流水線可以儘可能地減少應用程式和Redis之間的通訊往返次數,但是對於一個已

nginx安全效能優化(上部)

Nginx——Ngine X,是一款自由的、開源的、高效能HTTP伺服器和反向代理伺服器;也是一個IMAP、POP3、SMTP代理伺服器;也就是說Nginx本身就可以託管網站(類似於Tomcat一樣),進行Http服務處理,也可以作為反向代理伺服器使用。 Nginx 解

redis的資料安全效能保障

快照持久化方式:可以將存在於某一時刻的所有資料都寫入硬盤裡面。 只追加檔案:(append-only file,AOF),它會在執行寫命令時,將被執行的寫命令複製到硬盤裡面。 redis.conf引數配置: save 900 1, 900秒內有一次寫入,存入快照 save

php 客戶端伺服器端安全破解

一般的加密和授權:轉發伺服器(代理伺服器) 解決方案:hhvm編譯程式碼   放扒取: js類 1:防止滑鼠右鍵事件,在html->body <body oncontextmenu=self.event.returnValue=false> 或

(轉)PHP執行緒安全非執行緒安全的區別:如何選擇用哪一個?

PHP執行緒安全與非執行緒安全的區別:如何選擇用哪一個? 很多時候,我們在做PHP環境配置的時候,很多人都是直接去亂下載PHP版本的,但是他不清楚:從2000年10月20日釋出的第一個Windows版的PHP3.0.17開始的都是執行緒安全的版本,直至5.2.1版本開始有Thread Safe

iOS中保證執行緒安全的幾種方式效能對比

一、前言 前段時間看了幾個開源專案,發現他們保持執行緒同步的方式各不相同,有@synchronized、NSLock、dispatch_semaphore、NSCondition、pthread_mutex、OSSpinLock。後來網上查了一下,發現他們的實現機制各不相同,效能也各不一

php檔案包含目錄配置open_basedir的使用效能分析

1.open_basedir介紹 open_basedir 將php所能開啟的檔案限制在指定的目錄樹中,包括檔案本身。當程式要使用例如fopen()或file_get_contents()開啟一個檔案時,這個檔案的位置將會被檢查。當檔案在指定的目錄樹之外,程式

HTTP攻擊防範--PHP安全配置

1什麼是安全性 所謂安全性就是保護web應用程式與網頁不會受到黑客的攻擊。有些黑客純粹是為了好玩而入侵他人的電腦,但有更多的黑客費勁心思要竊取他人電腦中的機密檔案,甚至使整臺電腦癱瘓來達到他的目的。現象在網上有很多可以讓黑客使用的軟體,這些軟體多半是免費的而且簡單好用,

PHP的執行緒安全非執行緒安全

什麼是執行緒安全? Thread Safety means that binary can work in a multithreaded webserver context, such as Apache 2 on Windows. Thread Sa

windows下php執行緒安全非執行緒安全的版本選擇

Windows下的PHP版本分兩種:執行緒安全版本與非執行緒安全版本。 要論兩者的區別,詳細論說起來比較麻煩,從使用者的角度,記住什麼時候用哪種版本的區別就可以了吧: 1、windows + IIS + FastCGI :使用非執行緒安全版本。

Tomcat8安裝, 安全配置效能優化

 為了便於檔案管理,個人習慣  在/opt目錄下建立 一個install目錄用於存放 軟體安裝包,在/usr 目錄下建立local資料夾使用者存放解壓檔案 下載安裝包: wget http://apache.fayea.com/tomcat/tomcat-8/v8.0.32/bin/apache-tomc

PHP-執行緒安全非執行緒安全版本的區別

Windows版的PHP從版本5.2.1開始有Thread Safe(執行緒安全)和None Thread Safe(NTS,非執行緒安全)之分,這兩者不同在於何處?到底應該用哪種?這裡做一個簡單的介紹。       從2000年10月20日釋出的第一個Windows版的P

PHP安全防範程式設計

 簡介   當開發一個網際網路服務的時候,必須時刻牢記安全觀念,並在開發的程式碼中體現。PHP指令碼語言對安全問題並不關心,特別是對大多數沒有經驗的開發者來說。每當你講任何涉及到錢財事務等交易問題時,需要特別注意安全問題的考慮,例如開發一個論壇或者是一個購物車

ISAPI、CGI、FASTCGI、PHP-FPM執行緒安全、執行緒非安全

ISAPI:Internet Server Application Programming Interface,是種協議,對應語言的實現就是對應的伺服器擴充套件(以動態連結庫dll形式存在)。一個ISAPI的DLL,可以在被使用者請求啟用後長駐記憶體,等待使用者的另一個請求,還可以在一個DLL裡設定多個使用

PHP執行緒安全非執行緒安全的區別

       轉載自:http://koda.iteye.com/blog/662034        Windows版的PHP從版本5.2.1開始有Thread Safe(執行緒安全)和None Thread Safe(NTS,非執行緒安全)之分,這兩者不同在於何處?到

PHP 分支循環和goto

obj 所有 結構化 eal ray 流程控制 ont 如果 string 分支與循環 1、if中的判斷條件is_bool():判斷是否是布爾型is_int()、is_integer()和is_long():判斷是否為整型。is_float()、is_double()和is

php--strlen()mb_strlen的作用區別

encoding 字符串長度 php.ini php odin int 字節數 ring enc 在PHP中,strlen與mb_strlen是求字符串長度的函數PHP內置的字符串長度函數strlen無法正確處理中文字符串,它得到的只是字符串所占的字節數。對於GB2312的