新聞中心
一、前言

php因天生支持web應(yīng)用的開發(fā),以其簡(jiǎn)單易學(xué),開發(fā)效率高而備受喜愛。使其占據(jù)了大片的市場(chǎng)。但是php本身的安全問題卻一直不曾消停,以及不規(guī)范的php代碼編寫規(guī)范,使得web應(yīng)用漏洞百出。這篇文章從配置文件和代碼編寫角度出發(fā),總結(jié)記錄php相關(guān)安全。新手上路,向前輩致敬。
二、請(qǐng)充分了解你的php
1. 基本信息
注意到以下的文件結(jié)構(gòu)在新版本php或者不同的發(fā)行版中略有不同,就好比在ubuntu18.04中安裝php7就和下面的文件結(jié)構(gòu)有較大的差別,所以下面的文件僅僅作為一個(gè)apache的架構(gòu)參考。
- Root:/var/www/html
- 默認(rèn)Web服務(wù):Apache(可以使用Lighttpd或Nginx代替)
- 默認(rèn)PHP配置文件:/etc/php.ini
- 默認(rèn)PHP Extensions
- 配置目錄:/etc/php.d/
- PHP安全配置樣例文件:/etc/php.d/security.ini(需要使用文本編輯器創(chuàng)建這個(gè)文件)
- php 版本: php -v
- 查看當(dāng)前PHP所編譯 : php -m
2. 敏感配置
以下是一些常見的配置舉例,更多請(qǐng)查看:
http://php.net/manual/zh/ini.core.php#ini.variables-order。
不在請(qǐng)求頭中泄露php信息:
- expose_php=Off
不回顯php錯(cuò)誤(包括運(yùn)行錯(cuò)誤時(shí)和啟動(dòng)時(shí)錯(cuò)誤),但是進(jìn)行錯(cuò)誤記錄:
- play_errors=Off
- display_startup_errors=off
- log_errors=On
- error_log=/var/log/httpd/php_scripts_error.log
文件上傳開啟與否和最大上傳文件限制:
- file_uploads=On
- upload_max_filesize=1M
控制最大post數(shù)據(jù):
- post_max_size=1M
注意:到要比upload_max_filesize大,否則后者失效。
關(guān)閉遠(yuǎn)程代碼執(zhí)行:
- allow_url_fopen=Off
- allow_url_include=Off
關(guān)閉全局注冊(cè)變量,不過默認(rèn)5.x版本的php是off:
- register_globals=off
關(guān)于安全模式和粗暴的魔術(shù)引號(hào)過濾,注意到save_mode模式在php5.3以上版本,safe_mode被棄用,在php5.4以上版本,則將此特性完全去除了:
- safe_mode=On
- safe_mode_include_dir = D:/phpstudy/www/include/
- magic_quotes_gpc=Off #如果開啟了這個(gè),然后在php應(yīng)用中使用addslashes()過濾輸入會(huì)造成雙重轉(zhuǎn)義,使得過濾無濟(jì)于事,遇到這種情況時(shí)可以使用函數(shù) get_magic_quotes_gpc() 進(jìn)行檢測(cè)。
- magic_quotes_runtime
資源管理防止過分消耗服務(wù)器資源:
- max_execution_time = 30
- max_input_time = 30
- memory_limit = 40M
禁用危險(xiǎn)函數(shù):
- disable_functions =
- phpinfo,eval,passthru,assert,exec,system,ini_set,ini_get,get_included_files,
- get_defined_functions,get_defined_constants,get_defined_vars,
- glob,``,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,
- ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,
- symlink,popepassthru,stream_socket_server,fsocket,fsockopen
限制php訪問文件系統(tǒng):
- open_basedir='/var/www/html/';......;......
session保存路徑:
- session.save_path="/var/lib/php/session"
上傳文件默認(rèn)路徑:
- upload_tmp_dir="/var/lib/php/upload"
3. 關(guān)于危險(xiǎn)函數(shù)
特殊符號(hào):
“:反引號(hào)運(yùn)算符在激活了安全模式或者關(guān)閉了 shell_exec() 時(shí)是無效的,同時(shí)與其它某些語言不同,反引號(hào)不能在雙引號(hào)字符串中使用。否則將會(huì)當(dāng)作shell命令執(zhí)行,執(zhí)行效果等同于shell_exec()。
- 文件操作:http://php.net/manual/zh/ref.filesystem.php。
- 全局信息,配置等:http://php.net/manual/zh/ref.info.php。
- 程序執(zhí)行:http://php.net/manual/zh/book.exec.php。
三、不要過分相信php
1. 弱類型
前人之述備矣,僅僅做個(gè)匯總。同樣還可以參看官網(wǎng)給出的類型表(PHP 類型比較表)。
- 0=='0' //true
- 0 == 'abcdefg' //true
- 1 == '1abcdef' //true
- null==false //true
- 123=='123' //true
- //哈希比較
- "0e132456789"=="0e7124511451155" //true
- "0e123456abc"=="0e1dddada" //false
- "0e1abc"=="0" //true
- "0x1e240"=="123456" //true
- "0x1e240"==123456 //true
- var_dump(intval('2')) //2
- var_dump(intval('3abcd')) //3
- var_dump(intval('abcd')) //0
- //任意兩個(gè)array,MD5相等
- var_dump(md5($array1)==var_dump($array2)); //true
- //case 自轉(zhuǎn)換,以下代碼輸出i is less than 3 but not negative
- $i ="2abc";
- switch ($i) {
- case 0:
- case 1:
- case 2:
- echo "i is less than 3 but not negative";
- break;
- case 3:
- echo "i is 3";
- }
- //in_array的缺陷,array_search
- $array=[0,1,2,'3'];
- var_dump(in_array('abc', $array)); //true
- var_dump(in_array('1bc', $array)); //true
- //strcmp在php5.x個(gè)版本后有些特性不太同,所以遇到的時(shí)候具體討論
2. 全局注冊(cè)變量
如果已經(jīng)棄用的 register_globals 指令被設(shè)置為 on 那么局部變量也將在腳本的全局作用域中可用。例如, $_POST['foo'] 也將以 $foo 的形式存在。這將會(huì)造成一些變量覆蓋,條件判斷繞過。以下是簡(jiǎn)化的全局變量認(rèn)證繞過模型:
- if(authenticated_user()){
- $authorized=true;
- }
- if($authorized){
- do something......
- }
對(duì)于以上的繞過,我們可以有以下的規(guī)避措施:(1) php.ini register_globals=off(2) 在每次判斷前初始化變量,如下:
- $authorized=false;
- if(authenticated_user()){
- $authorized=true;
- }
- if($authorized){
- do something......
- }
3. php偽協(xié)議
偽協(xié)議在很多繞過場(chǎng)景下發(fā)揮著舉足輕重的作用,如后面提到的文件包含file://協(xié)議繞過,以及最近才提出的phar協(xié)議反序列化對(duì)象注入,我們可以在不存在可控unserialization()函數(shù)的情況下利用phar反序列化對(duì)象,實(shí)現(xiàn)對(duì)象注入。所以在web應(yīng)用中不要忽視他們的存在,千里之堤,潰于蟻穴。
- file:///var/www/html 訪問本地文件系統(tǒng)
- ftp://:@ 訪問FTP(s) URLs
- data:// 數(shù)據(jù)流
- http:// — 訪問 HTTP(s) URLs
- ftp:// — 訪問 FTP(s) URLs
- php:// — 訪問各個(gè)輸入/輸出流
- zlib:// — 壓縮流
- data:// — Data (RFC 2397)
- glob:// — 查找匹配的文件路徑模式
- phar:// — PHP Archive
- ssh2:// — Secure Shell 2
- rar:// — RAR
- ogg:// — Audio streams
- expect:// — 處理交互式的流
四、向DVWA學(xué)習(xí)php安全的代碼編寫
以下樣例來自于DVWA v1.9版本
1. sql注入
(1) Low level
- if( isset( $_REQUEST[ 'Submit' ] ) ) {
- // Get input
- $id = $_REQUEST[ 'id' ];
- // Check database
- $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
- $result = mysql_query( $query ) or die( '
' . mysql_error() . '' );- // Get results
- $num = mysql_numrows( $result );
- $i = 0;
- while( $i < $num ) {
- // Get values
- $first = mysql_result( $result, $i, "first_name" );
- $last = mysql_result( $result, $i, "last_name" );
- // Feedback for end user
- echo "
ID: {$id}";
First name: {$first}
Surname: {$last}- // Increase loop count
- $i++;
- }
- mysql_close();
- }
- ?>
在這個(gè)例子中,是最low安全等級(jí)的php代碼編寫樣例,可以看到,代碼中并沒有對(duì)用戶輸入的id變量進(jìn)行檢查和過濾,同時(shí)使用的是$_REQUEST全局?jǐn)?shù)組的方式,如果不是特別需要,我們編程的時(shí)候盡量不要使用$_REQUEST獲取用戶的參數(shù),因?yàn)?_REQUEST的參數(shù)比較雜,包括$_GET,$_POST,$_COOKIE等超全局變量,并且二者還存在變量獲取順序的不一致,受配置文件中variables_order的約定,在存在waf的環(huán)境下,容易造成繞過。未經(jīng)處理的用戶輸入直接與sql語句拼接交互,造成sql注入漏洞,十分危險(xiǎn)。
(2) Medium level
- if( isset( $_POST[ 'Submit' ] ) ) { // Get input $id = $_POST[ 'id' ]; $id = mysql_real_escape_string( $id );
- // Check database
- $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
- $result = mysql_query( $query ) or die( '
' . mysql_error() . '' );- // Get results
- $num = mysql_numrows( $result );
- $i = 0;
- while( $i < $num ) {
- // Display values
- $first = mysql_result( $result, $i, "first_name" );
- $last = mysql_result( $result, $i, "last_name" );
- // Feedback for end user
- echo "
ID: {$id}";
First name: {$first}
Surname: {$last}- // Increase loop count
- $i++;
- }
- //mysql_close();
- }
- ?>
這個(gè)版本的代碼,與之前的相比只是多了個(gè)mysql_real_escape_string函數(shù)的過濾,但是要知道這里的$id在sql語句中是數(shù)字類型,這樣mysql_real_escape_string的轉(zhuǎn)義就會(huì)形同虛設(shè),注入仍舊是一馬平川。當(dāng)然不恰當(dāng)?shù)淖址幋a,可能會(huì)造成寬字節(jié)注入。
(3) High leval
- if( isset( $_SESSION [ 'id' ] ) ) {
- // Get input
- $id = $_SESSION[ 'id' ];
- // Check database
- $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
- $result = mysql_query( $query ) or die( '
Something went wrong.' );- // Get results
- $num = mysql_numrows( $result );
- $i = 0;
- while( $i < $num ) {
- // Get values
- $first = mysql_result( $result, $i, "first_name" );
- $last = mysql_result( $result, $i, "last_name" );
- // Feedback for end user
- echo "
ID: {$id}";
First name: {$first}
Surname: {$last}- // Increase loop count
- $i++;
- }
- mysql_close();
- }
- ?>
在高級(jí)版本中只是把注入點(diǎn)隱匿在了$_SESSION全局變量里面,而session中的id值的注冊(cè)是通過用戶輸入$_POST全局變量傳入,所以是完全可控的,這樣一來,就和之前的注入沒有什么不一樣。這段代碼是要提醒我們對(duì)于session,只要注冊(cè)值是用戶可控的,也是可能存在sql注入的風(fēng)險(xiǎn)的。另外需要注意到的是,在這個(gè)High級(jí)別的注入中,回顯和傳參頁面不是同一個(gè),是一個(gè)二階注入,如果使用工具注入,如sqlmap,別忘了加上自定義回顯–second-order參數(shù)。
(4) Impossible level
- if( isset( $_GET[ 'Submit' ] ) ) {
- // Check Anti-CSRF token
- checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
- // Get input
- $id = $_GET[ 'id' ];
- // Was a number entered?
- if(is_numeric( $id )) {
- // Check the database
- $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
- $data->bindParam( ':id', $id, PDO::PARAM_INT );
- $data->execute();
- $row = $data->fetch();
- // Make sure only 1 result is returned
- if( $data->rowCount() == 1 ) {
- // Get values
- $first = $row[ 'first_name' ];
- $last = $row[ 'last_name' ];
- // Feedback for end user
- echo "
ID: {$id}";
First name: {$first}
Surname: {$last}- }
- }
- }
- // Generate Anti-CSRF token
- generateSessionToken();
- ?>
根據(jù)DVWA的說法,這樣寫出來的應(yīng)用,是不存在sql注入的。也即這是個(gè)十分安全的php代碼編寫規(guī)范。why?首先,我們可以看到它使用Anti-CSRF token的方法來避免csrf攻擊(具體細(xì)節(jié)會(huì)在下文csrf防御談到),然后在sql語句的編寫中,使用的是預(yù)處理語句,所謂的預(yù)處理就是通過php的pdo預(yù)處理機(jī)制PDO::prepare,先往數(shù)據(jù)庫送出語句模板,進(jìn)行解析,編譯,然后第二次向數(shù)據(jù)庫傳入查詢參數(shù),在第二次的查詢過程中可以理解為不再進(jìn)行語義解析,所以即使傳入sql語句,也會(huì)因?yàn)椴贿M(jìn)行語義解析而失效。所以這是一種比較推薦的數(shù)據(jù)庫交互sql語句編寫規(guī)范?,F(xiàn)在很多主流的數(shù)據(jù)庫已經(jīng)支持預(yù)處理,即使不支持,PHP的PDO也會(huì)進(jìn)行預(yù)處理模擬實(shí)現(xiàn),這樣對(duì)于程序員接口一致,不需了解不同數(shù)據(jù)庫對(duì)預(yù)處理支持的方式差異。
- 更多PDO細(xì)節(jié)可以參考官網(wǎng):http://php.net/manual/zh/pdo.prepared-statements.php。
- 參數(shù)bind的細(xì)節(jié)可以參考:http://php.net/manual/zh/pdo.constants.php。
2. CSRF
完整的攻擊過程,可以看這篇前輩的文章:http://www.freebuf.com/articles/web/118352.html。
(1) Low level
- if( isset( $_GET[ 'Change' ] ) ) {
- // Get input
- $pass_new = $_GET[ 'password_new' ];
- $pass_conf = $_GET[ 'password_conf' ];
- // Do the passwords match?
- if( $pass_new == $pass_conf ) {
- // They do!
- $pass_new = mysql_real_escape_string( $pass_new );
- $pass_new = md5( $pass_new );
- // Update the database
- $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
- $result = mysql_query( $insert ) or die( '
' . mysql_error() . '' );- // Feedback for the user
- echo "
Password Changed.";- }
- else {
- // Issue with passwords matching
- echo "
Passwords did not match.";- }
- mysql_close();
- }
- ?>
所謂的CSRF(Cross-site request forgery)直白的翻譯就是跨站點(diǎn)請(qǐng)求偽造。說人話就是攻擊者通過誘使victim訪問其精心構(gòu)造的url或者訪問其精心構(gòu)造的頁面,來使得攻擊者可以以victim的身份做諸如發(fā)郵件,發(fā)消息,改密碼等騷操作。在DVWA這個(gè)系列里面,模擬的是修改密碼的界面。先來看下low等級(jí)的代碼,可以說是沒有進(jìn)行仍和的再認(rèn)證,試下為啥是“再認(rèn)證”?其實(shí)我們?cè)谠L問到這個(gè)修改密碼界面的時(shí)候,已經(jīng)登陸過一次,服務(wù)器會(huì)在每次訪問時(shí)檢查session。所以這是第一道認(rèn)證。但是這種會(huì)話級(jí)別的認(rèn)證對(duì)csrf是沒有抵抗力的。具體的過程可以參看之前提到的鏈接。我們可以直接構(gòu)造url:
http://localhost/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#。
讓victim訪問,或者使用更加隱匿的:
構(gòu)造無跡表單,結(jié)合js發(fā)送請(qǐng)求,或者:
來實(shí)現(xiàn)欺騙隱匿行蹤,達(dá)到修改密碼的目的。順便盜用兩個(gè)別人的poc方便展示:
圖片形式誘導(dǎo)
![]()
404
file not found.
隱藏表單的形式
- New password:
- Confirm new password:
- /body>
(2) Medium level
- if( isset( $_GET[ 'Change' ] ) ) {
- // Checks to see where the request came from
- if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
- // Get input
- $pass_new = $_GET[ 'password_new' ];
- $pass_conf = $_GET[ 'password_conf' ];
- // Do the passwords match?
- if( $pass_new == $pass_conf ) {
- // They do!
- $pass_new = mysql_real_escape_string( $pass_new );
- $pass_new = md5( $pass_new );
- // Update the database
- $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
- $result = mysql_query( $insert ) or die( '
' . mysql_error() . '' );- // Feedback for the user
- echo "
Password Changed.";- }
- else {
- // Issue with passwords matching
- echo "
Passwords did not match.";- }
- }
- else {
- // Didn't come from a trusted source
- echo "
That request didn't look correct.";- }
- mysql_close();
- }
- ?>
在這個(gè)級(jí)別的CSRF漏洞中,服務(wù)端多了一句eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ]校驗(yàn),ereg()函數(shù)是模式匹配,通過超全局?jǐn)?shù)組獲取了請(qǐng)求頭referer值(也就是訪問者向host發(fā)起請(qǐng)求時(shí)所在的頁面)和host值,并且檢查host的值是否在referer中出現(xiàn)。根據(jù)權(quán)威
(https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name),這兩個(gè)值無法以編程的方式修改,抓包除外,因?yàn)樵赾srf中無法通過抓取客戶端的包進(jìn)行修改,所以按理來說是安全的。實(shí)則不然,通過公網(wǎng)服務(wù)器,誘使victim訪問名字包含host的html文件就可以實(shí)現(xiàn)繞過。
(3) High level
- if( isset( $_GET[ 'Change' ] ) ) {
- // Check Anti-CSRF token
- checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
- // Get input
- $pass_new = $_GET[ 'password_new' ];
- $pass_conf = $_GET[ 'password_conf' ];
- // Do the passwords match?
- if( $pass_new == $pass_conf ) {
- // They do!
- $pass_new = mysql_real_escape_string( $pass_new );
- $pass_new = md5( $pass_new );
- // Update the database
- $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
- $result = mysql_query( $insert ) or die( '
' . mysql_error() . '' );- // Feedback for the user
- echo "
Password Changed.";- }
- else {
- // Issue with passwords matching
- echo "
Passwords did not match.";- }
- mysql_close();
- }
- // Generate Anti-CSRF token
- generateSessionToken();
- ?>
在高級(jí)別中的代碼,主要是使用了Anti-csrf機(jī)制,用戶每次訪問改密頁面時(shí),服務(wù)器會(huì)返回一個(gè)隨機(jī)的token,向服務(wù)器發(fā)起請(qǐng)求時(shí),需要提交token參數(shù),而服務(wù)器在收到請(qǐng)求時(shí),會(huì)優(yōu)先檢查token,只有token正確,才會(huì)處理客戶端的請(qǐng)求。我們可以按F12來看看這個(gè)token:
可以看到不同的用戶會(huì)返回一個(gè)不同的token,這個(gè)token在hidden欄里面,這樣一來,迫于同源策略,攻擊者無法獲取victim的token,也就無法實(shí)現(xiàn)CSRF攻擊。但是真的無法實(shí)現(xiàn)嗎?配合xss我們還是可以盜取token的,但是這難度無疑增大,我們必須要有服務(wù)器的一個(gè)xss漏洞來盜取token,然后再使用CSRF。攻擊成本也增大。
(4) Impossible level
- if( isset( $_GET[ 'Change' ] ) ) {
- // Check Anti-CSRF token
- checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
- // Get input
- $pass_curr = $_GET[ 'password_current' ];
- $pass_new = $_GET[ 'password_new' ];
- $pass_conf = $_GET[ 'password_conf' ];
- // Sanitise current password input
- $pass_curr = stripslashes( $pass_curr );
- $pass_curr = mysql_real_escape_string( $pass_curr );
- $pass_curr = md5( $pass_curr );
- // Check that the current password is correct
- $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
- $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
- $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
- $data->execute();
- // Do both new passwords match and does the current password match the user?
- if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
- // It does!
- $pass_new = stripslashes( $pass_new );
- $pass_new = mysql_real_escape_string( $pass_new );
- $pass_new = md5( $pass_new );
- // Update database with new password
- $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
- $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
- $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
- $data->execute();
- // Feedback for the user
- echo "
Password Changed.";- }
- else {
- // Issue with passwords matching
- echo "
Passwords did not match or current password incorrect.";- }
- }
- // Generate Anti-CSRF token
- generateSessionToken();
- ?>
在high的基礎(chǔ)上,直接進(jìn)行了密碼再認(rèn)證,這樣一來,即使盜取了token,沒有原始密碼,也無法進(jìn)行修改密碼的操作,這樣CSRF就可以完全避免了。所以通過這個(gè)CSRF系列,我們可以知曉,在csrf防御中,采用關(guān)鍵操作的原子性認(rèn)證,是避免這一漏洞攻擊的不二辦法。其實(shí)我們只關(guān)注了CSRF部分,在之前的level中,也還存在了sql注入,在這個(gè)impossible版本里,還使用了之前提到的預(yù)操縱來進(jìn)行數(shù)據(jù)庫交互,降低了sql注入的風(fēng)險(xiǎn)。
3. Command Injection
(1) Low level
- if( isset( $_POST[ 'Submit' ] ) ) {
- // Get input
- $target = $_REQUEST[ 'ip' ];
- // Determine OS and execute the ping command.
- if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
- // Windows
- $cmd = shell_exec( 'ping ' . $target );
- }
- else {
- // *nix
- $cmd = shell_exec( 'ping -c 4 ' . $target );
- }
- // Feedback for the end user
- echo "
{$cmd}";- }
- ?>
過分相信用戶的輸入,直接拼接到ping 命令中,會(huì)造成命令注入。注意到常用的bash命令拼接的方式有||.&&,|,&,;這五個(gè),所以由于沒有過濾完全,我們直接進(jìn)行命令拼接,然后執(zhí)行任意命令,如127.0.0.1;cat /etc/passwd。
(2) Medium level
- if( isset( $_POST[ 'Submit' ] ) ) {
- // Get input
- $target = $_REQUEST[ 'ip' ];
- // Set blacklist
- $substitutions = array(
- '&&' => '',
- ';' => '',
- );
- // Remove any of the charactars in the array (blacklist).
- $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
- // Determine OS and execute the ping command.
- if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
- // Windows
- $cmd = shell_exec( 'ping ' . $target );
- }
- else {
- // *nix
- $cmd = shell_exec( 'ping -c 4 ' . $target );
- }
- // Feedback for the end user
- echo "< 網(wǎng)頁名稱:淺談PHP安全規(guī)范
文章分享:http://m.5511xx.com/article/dhicihg.html


咨詢
建站咨詢
