動作

PHP Sudo

出自 Itsmw

簡介

 本文在介紹如何使用 php 5.4(或以上)的版本,建立一個可由 php 程式碼,呼叫各種需 linux root 執行權限程式指令的網頁環境。

緣起

 若我們要使用 PHP 開發一套 WEB 介面的伺服器設定工具時,會面臨「用 PHP 的 shell_exec() 執行 Linux Command 時權限不足」的問題。這是因為一般的 WEB Server 預設是由 www-data 這個身份啟動,而它並不具 root 權限。而且為了資安,我們不能單純的 visudo 直接給它 sudo 權力。



實作

 不論是 apache2 或 nginx 要在原 80 埠外,再產生一組 WEB 環境都是做得到的,但都有點複雜。剛好 2012-03-01 時 PHP 官方發佈了 PHP 5.4 版,此版起內建了一個供程式測試用途之網頁伺服器(a built-in webserver for testing purposes)。也就是說,它不必依附在 apache2 或 nginx 底下,直接就可以顯示網頁,或許它不強大,也無法處理大流量壓力,但卻符合筆者「建立WEB版伺服器設定工具」的需求,誰會把設定工具開放給百千人上來瀏覽? 加上其簡單的構造,因此筆者決定採用這個方案。


 本文所提的方案如下:

  1. 把 PHP 升級為 5.4 版
  2. 建立一個 linux user ,並賦予其 NO Password 的 sudo 權限
  3. 用此 linux user 身份啟動 php5 web server 功能,並取一個空閒的通訊埠,等待 client 連線服務。



升級至 php 5.4 版

 Ubuntu 11.04/11.10/12.04 皆可以簡單的依下列步驟升級至 PHP 5.4 版,做法如下:

  • 切換至 root 身份
    user@dns:~# sudo -i
  • 加入 php 最新版來源庫
    • root@dns:~# add-apt-repository ppa:ondrej/php5
    • root@dns:~# apt-get update
  • PHP 升級
    由於有些 php 週邊模組並未支援此來源庫所提供的 PHP 5.4 ,比較重要的是php5-suhosin, php5-imagick 及 php-apc 等,若您的站台有需要上述幾個,請勿繼續安裝。若已安裝,但可被移除,那就強制升級:
    root@dns:~# apt-get -f install php5 php5-cli php5-common php5-fpm php5-gd php-pear libapache2-mod-php5 php5-mcrypt php5-mysql php5-xmlrpc php5-xsl
下列的額外套件將被安裝:
  libonig2 php5-snmp libqdbm14 psmisc
下列套件將會被【移除】:
  php-apc php5-adodb php5-imagick php5-suhosin
下列【新】套件將會被安裝:
  libonig2 libqdbm14
下列套件將會被升級:
  libapache2-mod-php5 php5 php5-cli php5-common php5-gd php5-mcrypt php5-mysql php5-fpm
  php5-snmp php5-xmlrpc php5-xsl psmisc
升級 12 個,新安裝 2 個,移除 4 個,有 2 個未被升級。
需要下載 6,319 kB 的套件檔。
此操作完成之後,會空出 868 kB 的磁碟空間。
是否繼續進行 [Y/n]?

   註:會出現 php5-snmp 將會被安裝,那是原本 5.3 時已裝過,但指令裡沒提到它。


  • 重新啟動 apache2 或 nginx
    • apache2 方案
      root@dns:~# service apache2 restart
    • nginx 方案
      root@dns:~# service php5-fpm restart
      root@dns:~# service nginx restart
  • 重新啟動 web server 與「建立可 sudo PHP 網頁環境」無關,只是因為 PHP 核心程式升級,連帶要重啟呼叫它的母程式。



建一個可 sudo 的 linux user

 所謂 NO Password 的 sudo 帳號是指,在下「sudo xxxxx」指令時,不必再 key 一次密碼,不是指不必密碼就可登入系統。

  • 建立 linux user,以「bakuadm」為例
    root@dns:~# adduser bakuadm
正在新增使用者 `bakuadm' ...
增加新群組 `bakuadm' (1002) ...
正在新增新使用者 `bakuadm' (UID 1002) 到群組 `bakuadm' ...
Creating home directory `/home/bakuadm' ...
Copying files from `/etc/skel' ...
輸入新的 UNIX 密碼: 
再次輸入新的 UNIX 密碼: 
passwd:密碼已成功地變更
正在改變 bakuadm 的使用者訊息
請輸入新值,或直接按 ENTER 鍵以使用預設值
	全名 []: 
	房間號碼 []: 
	工作電話 []: 
	住家電話 []: 
	其它 []: 
以上輸入的資料正確嗎?[Y/n] y

  注意:該 user 的密碼不可太過簡單

  • 賦予 NO-Password 的 sudo 權限
    • 修改 sudo 設定檔
      root@dns:~# visudo
    • 加入「bakuadm ALL=NOPASSWD: ALL」至 root 底下,如下所示
...

# User privilege specification
root    ALL=(ALL:ALL) ALL
bakuadm ALL=NOPASSWD: ALL

...

  註:

  1. 若是使用預設的 nano 編輯器,寫完後,按 Ctrl-O 儲存,再按 Ctrl-X 離開
  2. 若要用到指令不多,最好不要給予「ALL」權限,可限定只能使用部份指令,寫法可參考: https://help.ubuntu.com/community/Sudoers


  • 以 bakuadm 登入本機,進行測試
    root@dns:~# ssh -l bakuadm localhost (此步驟,要密碼認證)
bakuadm@localhost's password: 
  • 執行需 root 權限的 apt-get update 試試看
    bakuadm@dns:~# sudo apt-get update
  • 若沒問密碼,便立即執行,那便成功了。



以該 user 在 port 80 外另起一個 PHP WEB 環境

 最後這個動作就是重點了,我們要以 bakuadm 這身份,另起一個支援 PHP 的網頁環境。此時,您可能會有一個疑問,為何不直接用 root 啟動就好。筆者是認為 root 的權限太大了,另建一個雖在 sudo 時 NO Password 但只能執行部份指令的 user 才是安全之道。

  • 以 ssh 的方式登入 bakuadm
    root@dns:~# ssh -l bakuadm localhost
  • 準備好網頁文件資料夾及測試用的 index.php
    • bakuadm@dns:~$ mkdir html
    • bakuadm@dns:~$ cd html
    • bakuadm@dns:~/html$ vi index.php
<?php
$strExec = "";
$strExec = shell_exec("sudo apt-get update");
if( $strExec == "" ){
	$strMain = "<h3 style='text-align: center; color: red;'>sudo 執行失敗</h3>";
}else{
	$strMain = "
	<h3 style='text-align: center;'>sudo apt-get update執行結果</h3>
	<DIV style='margin: 0 auto; width: 600px; padding: 8px; background: #ADD8E6;'>
	".nl2br(htmlspecialchars($strExec))."
	</DIV>";
}
?>
<HTML>
<head>
	<meta http-equiv='content-type' content='text/html; charset=utf-8' />
</head>
<body>
<?php echo $strMain; ?>
</body>
</HTML>


  • 在 TCP port 3000 背景執行 php web server
    • 只限本機才可瀏覽
      bakuadm@dns:~/html$ php -S localhost:3000 -t /home/bakuadm/html/ &
    • 其他 IP 也可瀏覽
      bakuadm@dns:~/html$ php -S 192.168.1.1:3000 -t /home/bakuadm/html/ &
    • 說明一: -S 是指要開啟服務的主機名及通訊埠 
    • 說明二: -t 是網頁文件根目錄
    • 說明三:最後加「&」是為了在背景執行,因此成功在 3000 埠提供服務後,便可把 bakuadm 登出。


  • 中止服務
    • 用「ps aux |grep php」或「netstat -nltp」查出 PID 後,再用 kill 指令中斷執行即可




本文小檔案

題名: Title::用 PHP 建立可執行 sudo 指令的網頁環境
作者: Creator::itsmw作者群
主題/關鍵詞: Subject::php, web server, sudo
簡述: Description::由 php 程式碼,呼叫各種需 linux root 執行權限程式指令的網頁環境
出版者: Publisher::MyIP itsmw 計畫
其他參與者: Contributor::itsmw作者群
日期: Date::2012-3-27
文件類型: Type::08伺服器軟體
資料格式: Format::text/html
文件識別代號: Identifier::http://myip.tw/itsmw/index.php?title=PHP_Sudo
來源: Source::http://myip.tw/itsmw
語言: Language::zh-TW
相關資源: Relation::http://www.php.net/
文件涵蓋範圍: Coverage::Linux平台
版權規範: Rights::GNU Free Documentation License 1.2