1.2 Boa的特點
在μClinux中常用的Web伺服器有:Boa,thttpd,httpd,其中httpd只支援靜態頁面,顯然不適合進階應用程式,thttpd和 Boa所提供的功能基本一樣,但是thttpd在運行過程中所需要的資源要遠大於Boa,因此使用Boa作為該嵌入式系統的Web伺服器。系統的軟體開發模型選用B/S模型。
Boa是一個高效能的單任務型Web伺服器,可以運行在幾乎所有的類Unix的平台上,Boa支援認證,支援CGI,功能比較全,佔用資源也少,非常適合於用在資源有限的嵌入式系統中,目前Boa已經以源碼的形式包含在μClinux的發行包中。
2 Boa源碼分析
在此通過以下對Boa的原始碼進行簡單的分析,來提出解決避免惡意攻擊的安全解決方案。
2.1 Boa工作流程
圖1是Boa工作流程圖。Boa從新到達的通訊端獲得HTTP請求(由一個request結構來儲存),並將其儲存在隊列當中。首先,get_request()將從通訊端獲得的資料全部儲存在request→header_line中,然後調用process_request() 來處理在隊列中的每一個請求。根據request結構中status所表示的不同狀態,將進行不同的處理。如果這個請求符合HTTP協議,則會調用
process_option_Iine()將一些頭部資訊填寫到request結構中完成這些環境變數的設定,隨後 process_header_end()會對使用者進行驗證。如果驗證通過則判斷request結構中的is_cgi,非0則是CGI程式,調用 init_cgi()函數進行處理,為0則是靜態頁面,調用init_get()函數進行處理。
2.2 init_get函數工作流程
圖2為處理靜態頁面請求的init_get()函數的基本工作流程。圖2中process_get()函數完成的功能為將request結構中的data_men字串返回通訊端並在使用者瀏覽器上顯示相應的內容。
2.3 init_cgi函數工作流程
對CGI程式的處理函數init_cgi()首先調用一系列函數完成對CGI環境變數的設定,create_common_env(),complete_env()完成了大多數CGI環境變數的註冊工作。採用PIPE(管道)方式,就是將 CGI程式的輸出重新導向到管道,然後Boa從管道讀取並轉寄給用戶端瀏覽器。整個流程結束後,返回到主函數的無限迴圈中等待處理下一個通訊端串連的到達。
init_cgi()具體工作流程3所示。
管道讀取函數read_from_pipe()完成的主要功能是從通訊端req→data_fd讀取資料到req→header_end中,並進行處理;然後修改req→status=PIPE_WRITE來調用write_from_pipe()將req→header_line的內容返回通訊端fd,並在使用者瀏覽器上顯示相應的內容。
3 Boa源碼改進
經過上述對Boa源碼的分析可以看出,Boa伺服器將根據瀏覽器地址欄中輸入的檔案路徑調用相應的CGI程式或靜態頁面顯示在瀏覽器中。這種方式使入侵者很容易找到源檔案,隱蔽性和安全性極差。這裡在對Boa源碼進行修改後,在瀏覽器中輸入對該系統指定的靜態網頁類型的請求後,Boa伺服器會自動進行檔案路徑重新導向,調用相應的CGI程式進行處理,而使用者不會察覺到這一變化。從而使使用者無法得知源檔案的路徑,增加了程式的隱蔽性和安全性。
在原始碼判斷是否CGI程式之前添加判斷:如果檔案路徑(req→pathname)的尾碼代表本系統指定的靜態頁面,則將其修改為實際CGI程式所在路徑,並更改is_cgi變數為“CGI”。經過這樣修改後,程式會調用CGI程式的處理函數init_cgi(),使原本的靜態請求變成動態CGI請求。修改後的Boa流程4所示(虛線為添加部分)。
4 CGI程式設計技術
4.1 CGI簡介
到目前為止,實現動態Web頁面有4種技術可供選擇:CGI,ASP,PHP和JSP。因為目前μClinux還不支援ASP,PHP等動態Web頁面技術,因此在該實現中選擇了CGI。
CGI規定Web伺服器調用其他可執行程式的介面協議標準,提供Web伺服器一個執行外部程式的通道。這種服務端技術使得瀏覽器和伺服器之間具有互動性。CGI程式屬於一個外部程式,需要編譯成可執行檔,以便在服務端運行。Web伺服器通過調用CGI程式實現與Web瀏覽器的互動,也就是CGI程式接收Web瀏覽器發送給Web
伺服器的資訊,進行處理,將響應結果再回送給Web伺服器及Web瀏覽器。
4.2 CGI程式工作原理
CGI工作原理如下:用戶端的使用者通過瀏覽器完成一定輸入工作後,向伺服器發出。HTTP請求(稱為CGI請求),伺服器守護進程,接收到該請求後,就建立一個子進程(稱為CGI進程)。該CGI子進程將CGI請求的有關資料設定成環境變數,在CGI程式與伺服器間建立兩台資料通道,然後啟動URL指定的CGI程式。子進程通過標準輸出資料流將處理結果傳遞給伺服器守護進程,守護進程再將處理結果作為應答訊息回送到用戶端。一個CGI程式的任務分為輸入任務和輸出任務。輸入任務根據要求方法的不同,從環境變數QUE-RY_STRING或標準輸入中讀取使用者輸入資料。輸出任務產生HTTP回應標頭標內容,如訊息本文的資料類型和資料長度等;產生HTTP響應訊息本文內容,如動態產生的HTML檔案內容。
4.3 CGI程式改進方法
傳統的CGI程式編寫方法簡單地用printf()函數來產生HTML原始碼。在輸出的字串中如果有雙引號,在其前面必須有一個後斜字元,這是因為整個HTML代碼串已經在雙引號內,所以HTML代碼串中的雙引號符必須用一個後斜字元來轉義。這樣的CGI程式碼冗長,不利於閱讀,且容易出錯。這裡所採用的方法是預先將需要顯示的網頁儲存成檔案,採用仿“ASP”的技術,將需要動態顯示的內容寫入符號“|%”與“|”之間。並設計設定檔,指定替換內容。CGI程式逐行讀取源檔案,將符號“|%”與“|”之間的內容替換成設定檔指定的內容。
HTML源檔案的格式設計如下:
選項按鈕:
CGI程式找出“|%”與“|”之間的關鍵字key,如果key中不包含“@”則直接替換與之對應的值;如果包含“@”,將關鍵字分為三部分:replacestr=checked,key=system_mode,keyvalue=route。尋找資料結構中與key相等的 name[i],將對應的value[i]與keyval-ue比較,如果相等則替換為type的值。具體流程5所示。
當在任意使用者端瀏覽器中輸入目標板的IP地址及對應的檔案名稱後,就會顯示6所示介面。其中在地址欄中輸入的路徑已經按照本文之前的方法被Boa伺服器修改,實際路徑為:http://192.168.0.1/cgi-bin/qs2.cgi。因此使用者無法找到源檔案,減小了被惡意使用者攻擊的可能性。圖5中選中單選框和添加文字框內容這些操作都是經過CGI程式替換顯示的設定檔中的內容。修改這些內容後點擊下一步程式會自動儲存到設定檔中,下一次再進入頁面後就會顯示上一次儲存的結果。