程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> PHP開發中常見的安全問題詳解和解決方法(如Sql注入、CSRF、Xss、CC等)

PHP開發中常見的安全問題詳解和解決方法(如Sql注入、CSRF、Xss、CC等)

編輯:PHP綜合

淺談Php安全和防Sql注入,防止Xss攻擊,防盜鏈,防CSRF

前言:

首先,筆者不是web安全的專家,所以這不是web安全方面專家級文章,而是學習筆記、細心總結文章,裡面有些是我們phper不易發現或者說不重視的東西。所以筆者寫下來方便以後查閱。在大公司肯定有專門的web安全測試員,安全方面不是phper考慮的范圍。但是作為一個phper對於安全知識是:“知道有這麼一回事,編程時自然有所注意”。

目錄:

1、php一些安全配置
(1)關閉php提示錯誤功能
(2)關閉一些“壞功能”
(3)嚴格配置文件權限。
2、嚴格的數據驗證,你的用戶不全是“好”人
2.1為了確保程序的安全性,健壯性,數據驗證應該包括內容。
2.2程序員容易漏掉point或者說需要注意的事項
3、防注入
   3.1簡單判斷是否有注入漏洞以及原理
   3.2常見的mysql注入語句
       (1)不用用戶名和密碼
       (2)在不輸入密碼的情況下,利用某用戶
       (3)猜解某用戶密碼
(4)插入數據時提權
(5)更新提權和插入提權同理
(6)惡意更新和刪除
(7)union、join等
(8)通配符號%、_
(9)還有很多猜測表信息的注入sql
   33防注入的一些方法
       2.3.1 php可用於防注入的一些函數和注意事項。
       2.3.2防注入字符優先級。
2.3.3防注入代碼
    (1)參數是數字直接用intval()函數
    (2)對於非文本參數的過濾
(3)文本數據防注入代碼。
(4)當然還有其他與addslashes、mysql_escape_string結合的代碼。
4、防止xss攻擊
4.1Xss攻擊過程
4.2常見xss攻擊地方
4.3防XSS方法
5、CSRF
5.1簡單說明CSRF原理
5.2防范方法
6、防盜鏈
7、防拒CC攻擊

1、php一些安全配置


(1)關閉php提示錯誤功能

在php.ini 中把display_errors改成
復制代碼 代碼如下:display_errors = OFF
或在php文件前加入
復制代碼 代碼如下:error_reporting(0)

1)使用error_reporting(0);失敗的例子:

A文件代碼:
復制代碼 代碼如下:<? 
error_reporting(0); 
echo 555 
echo 444; 
?>
錯誤:
復制代碼 代碼如下:Parse error: parse error, expecting `','' or `';'' in E:\webphp\2.php on line 4
2)使用error_reporting(0);成功的例子:
a文件代碼:
復制代碼 代碼如下:
<?php 
error_reporting(0); 
include("b.php"); 
?>
b文件代碼:
復制代碼 代碼如下:
<?php 
echo 555 
echo 444; 
?>
這是很多phper說用error_reporting(0)不起作用。第一個例子A.php裡面有致命錯誤,導致不能執行,不能執行服務器則不知有這個功能,所以一樣報錯。

第二個例子中a.php成功執行,那麼服務器知道有抑制錯誤功能,所以就算b.php有錯誤也抑制了。

ps:抑制不了mysql錯誤。

(2)關閉一些“壞功能”

1)關閉magic quotes功能

在php.ini 把magic_quotes_gpc = OFF
避免和addslashes等重復轉義

2)關閉register_globals = Off

在php.ini 把register_globals = OFF

在register_globals = ON的情況下

地址欄目:http://www.jb51.net?bloger=benwin
復制代碼 代碼如下:
<?php 
//$bloger = $_GET['bloger']   //因為register_globals = ON 所以這步不用了直接可以用$bloger
  echo $bloger; 
?>

這種情況下會導致一些未初始化的變量很容易被修改,這也許是致命的。所以把register_globals = OFF關掉

(3)嚴格配置文件權限。

為相應文件夾分配權限,比如包含上傳圖片的文件不能有執行權限,只能讀取

2、嚴格的數據驗證,你的用戶不全是“好”人。

記得筆者和一個朋友在討論數據驗證的時候,他說了一句話:你不要把你用戶個個都想得那麼壞!但筆者想說的這個問題不該出現在我們開發情景中,我們要做的是嚴格驗證控制數據流,哪怕10000萬用戶中有一個是壞用戶也足以致命,再說好的用戶也有時在數據input框無意輸入中文的時,他已經不經意變“壞”了。

2.1為了確保程序的安全性,健壯性,數據驗證應該包括

(1)     關鍵數據是否存在。如刪除數據id是否存在
(2)     數據類型是否正確。如刪除數據id是否是整數
(3)     數據長度。如字段是char(10)類型則要strlen判斷數據長度
(4)     數據是否有危險字符

數據驗證有些人主張是把功能完成後再慢慢去寫安全驗證,也有些是邊開發邊寫驗證。筆者偏向後者,這兩種筆者都試過,然後發現後者寫的驗證相對健壯些,主要原因是剛開發時想到的安全問題比較齊全,等開發完功能再寫時有兩個問題,一個phper急於完成指標草草完事,二是確實漏掉某些point。
2.2程序員容易漏掉point或者說需要注意的事項:

(1)     進庫數據一定要安全驗證,筆者在廣州某家公司參與一個公司內部系統開發的時候,見過直接把$_POST數據傳給類函數classFunctionName($_POST),理由竟然是公司內部使用的,不用那麼嚴格。暫且不說邏輯操作與數據操控耦合高低問題,連判斷都沒判斷的操作是致命的。安全驗證必須,沒任何理由推脫。
(2)     數據長度問題,如數據庫建表字段char(25),大多phper考慮到是否為空、數據類型是否正確,卻忽略字符長度,忽略還好更多是懶於再去判斷長度。(這個更多出現在新手當中,筆者曾經也有這樣的思想)
(3)     以為前端用js判斷驗證過了,後台不需要判斷驗證。這也是致命,要知道偽造一個表單就幾分鐘的事,js判斷只是為了減少用戶提交次數從而提高用戶體驗、減少http請求減少服務器壓力,在安全情況下不能防“小人”,當然如果合法用戶在js驗證控制下是完美的,但作為phper我們不能只有js驗證而拋棄再一次安全驗證。
(4)     缺少對表單某些屬性比如select、checkbox、radio、button等的驗證,這些屬性在web頁面上開發者已經設置定其值和值域(白名單值),這些屬性值在js驗證方面一般不會驗證,因為合法用戶只有選擇權沒修改權,然後phper就在後端接受數據處理驗證數據的時候不會驗證這些數據,這是一個慣性思維,安全問題也就有了,小人一個偽表單。
(5)     表單相應元素name和數據表的字段名一致,如用戶表用戶名的字段是user_name,然後表單中的用戶名輸入框也是user_name,這和暴庫沒什麼區別。
(6)     過濾危險字符方面如防注入下面會獨立講解。

3、防注入

3.1簡單判斷是否有注入漏洞以及原理。

網址:http://www.jb51.net/benwin.php?id=1 運行正常,sql語句如:select  *  from phpben where id = 1

(1) 網址:http://www.jb51.net/benwin.php?id=1'   sql語句如:select  *  from phpben where id = 1'  然後運行異常 這能說明benwin.php文件沒有對id的值進行“'” 過濾和intval()整形轉換,當然想知道有沒有對其他字符如“%”,“/*”等都可以用類似的方法窮舉測試(很多測試軟件使用)
(2)網址:http://www.jb51.net/benwin.php?id=1 and 1=1  則sql語句可能是 select  *  from phpben where id = 1 and 1=1,運行正常且結果和http://www.jb51.net/benwin.php?id=1結果一樣,則說明benwin.php可能沒有對空格“ ”、和“and”過濾(這裡是可能,所以要看下一點)
(3)網址:http://www.jb51.net/benwin.php?id=1 and 1=2則sql語句可能是 select  *  from phpben where id = 1 and 1=2 如果運行結果異常說明sql語句中“and 1=2”起作用,所以能3個條件都滿足都則很確定的benwin.php存在注入漏洞。

ps:這裡用get方法驗證,post也可以,只要把值按上面的輸入,可以一一驗證。

3.2常見的mysql注入語句。

(1)不用用戶名和密碼
復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben where user_name='admin' and pwd ='123'"; 
//在用戶名框輸入'or'='or'或 'or 1='1 然後sql如下 
$sql ="select * from phpben where user_name=' 'or'='or'' and pwd ='' "; 
$sql ="select * from phpben where user_name=' 'or 1='1' and pwd ='' ";
這樣不用輸入密碼。話說筆者見到登錄框都有嘗試的沖動。

(2)在不輸入密碼的情況下,利用某用戶。
復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben where user_name='$username' and pwd ='$pwd'"; 
//利用的用戶名是benwin 則用戶名框輸入benwin'#  密碼有無都可,則$sql變成 
$sql ="select * from phpben where user_name=' benwin'#' and pwd ='$pwd'";
這是因為mysql中其中的一個注悉是“#”,上面語句中#已經把後面的內容給注悉掉,所以密碼可以不輸入或任意輸入。網上有些人介紹說用“/*”來注悉,筆者想提的是只有開始注悉沒結束注悉“*/”時,mysql會報錯,也不是說“/**/”不能注悉,而是這裡很難添加上“*/”來結束注悉,還有“– ”也是可以注悉mysql 但要注意“–”後至少有一個空格也就是“– ”,當然防注入代碼要把三種都考慮進來,值得一提的是很多防注入代碼中沒把“– ”考慮進防注入范圍。

(3)猜解某用戶密碼
復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben.com where user_name='$username' and pwd ='$pwd'"; 
//在密碼輸入框中輸入“benwin' and left(pwd,1)='p'#”,則$sql是 
$sql ="select * from phpben.com where user_name=' benwin' and left(pwd,1)='p'#' and pwd ='$pwd'";
如果運行正常則密碼的密碼第一個字符是p,同理猜解剩下字符。

(4)插入數據時提權
復制代碼 代碼如下:
//正常語句,等級為1 
$sql = "insert into phpben.com (`user_name`,`pwd`,`level`) values(‘benwin','iampwd',1) "; 
//通過修改密碼字符串把語句變成 
$sql = "insert into phpben.com (`user_name`,`pwd`,`level`) values(‘benwin','iampwd',5)#',1) "; 
$sql = "insert into phpben.com (`user_name`,`pwd`,`level`) values(‘benwin','iampwd',5)--  ',1) ";這樣就把一個權限為1的用戶提權到等級5

(5)更新提權和插入提權同理
復制代碼 代碼如下:
//正常語句 
$sql = "update phpben set  `user_name` ='benwin', level=1"; 
//通過輸入用戶名值最終得到的$sql 
$sql = "update phpben set  `user_name` ='benwin',level=5#', level=1"; 
$sql = "update phpben set  `user_name` ='benwin',level=5--  ', level=1";

(6)惡意更新和刪除
復制代碼 代碼如下:
//正常語句 
$sql = "update phpben set `user_name` = ‘benwin' where id =1"; 
//注入後,惡意代碼是“1 or id>0” 
$sql = "update phpben set `user_name` = ‘benwin' where id =1 or id>0"; 
//正常語句 
$sql = "update phpben set  `user_name` ='benwin' where id=1"; 
//注入後 
$sql = "update phpben set  `user_name` ='benwin' where id>0#' where id=1"; 
$sql = "update phpben set  `user_name` ='benwin' where id>0-- ' where id=1";

(7)union、join等
復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben1 where `user_name`='benwin' "; 
//注入後 
$sql ="select * from phpben1 where`user_name`='benwin' uninon select * from phpben2#' "; 
$sql ="select * from phpben1 where`user_name`='benwin' left join……#' ";

(8)通配符號%、_
復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben where `user_name`='benwin' "; 
//注入通配符號%匹配多個字符,而一個_匹配一個字符,如__則匹配兩個字符 
$sql ="select * from phpben where `user_name` like '%b' "; 
$sql ="select * from phpben where `user_name` like '_b_' ";
這樣只要有一個用戶名字是b開頭的都能正常運行,“ _b_”是匹配三個字符,且這三個字符中間一個字符時b。這也是為什麼有關addslashes()函數介紹時提示注意沒有轉義%和_(其實這個是很多phper不知問什麼要過濾%和_下劃線,只是一味的跟著網上代碼走)

(9)還有很多猜測表信息的注入sql

復制代碼 代碼如下:
//正常語句 
$sql ="select * from phpben1 where`user_name`='benwin'"; 
//猜表名,運行正常則說明存在phpben2表 
$sql ="select * from phpben1 where`user_name`='benwin' and (select count(*) from phpben2 )>0#' "; 
//猜表字段,運行正常則說明phpben2表中有字段colum1 
$sql ="select * from phpben1 where`user_name`='benwin' and (select count(colum1) from phpben2 )>0#'"; 
//猜字段值 
$sql ="select * from phpben1 where`user_name`='benwin' and left(pwd,1)='p'#''";

當然還有很多,筆者也沒研究到專業人士那種水平,這裡提出這些都是比較常見的,也是phper應該知道並掌握的,而不是一味的在網上復制粘貼一些防注入代碼,知然而不解其然。

下面一些防注入方法回看可能更容易理解。

3.3防注入的一些方法

3.3.1 php可用於防注入的一些函數和注意事項。

(1)addslashes 和stripslashes。

Addslashes給這些 “'”、“””、“\”,“NULL” 添加斜桿“\'”、“\””、“\\”,“\NULL”, stripslashes則相反,這裡要注意的是php.ini是否開啟了magic_quotes_gpc=ON,開啟若使用addslashes會出現重復。所以使用的時候要先get_magic_quotes_gpc()檢查

一般代碼類似:
復制代碼 代碼如下:
if(!get_magic_quotes_gpc()) 

         $abc = addslashes($abc); 
}
其實這個稍微學習php一下的人都知道了,只不過筆者想系統點介紹(前面都說不是專家級文章),所以也順便寫上了。addslashes

(2)mysql_escape_string()和mysql_ real _escape_string()

mysql_real_escape_string 必須在(PHP 4 >= 4.3.0, PHP 5)的情況下才能使用。否則只能用 mysql_escape_string
復制代碼 代碼如下:
if (PHP_VERSION >= '4.3') 

$string  =  mysql_real_escape_string($string); 
}else 

$string  =  mysql_escape_string($string ); 
}
mysql_escape_string()和mysql_ real _escape_string()卻別在於後者會判斷當前數據庫連接字符集,換句話說在沒有連接數據庫的前提下會出現類似錯誤:
復制代碼 代碼如下:
Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user 'ODBC'@'localhost' (using password: NO) in E:\webphp\test.php on line 11

(3)字符代替函數和匹配函數
str_replace() 、perg_replace()這些函數之所以也在這裡提是因為這些函數可以用於過濾或替代一些敏感、致命的字符。

3.3.2防注入字符優先級。

防注入則要先知道有哪些注入字符或關鍵字,常見的mysql注入字符有字符界定符號如“'”、“””;邏輯關鍵字如“and”、“or”;mysql注悉字符如“#”,“– ”,“/**/”;mysql通配符“%”,“_”;mysql關鍵字“select|insert|update|delete|*|union|join|into|load_file|outfile”

(1)對於一些有規定格式的參數來說,防注入優先級最高的是空格” ”。

如一些銀行卡號,身份證號,郵箱,電話號碼,,生日,郵政編碼等這些有自己規定的格式且格式規定不能有空格符號的參數,在過濾的時候一般最先過濾掉空格(包括一些空格“變種”),因為其他字符界定符號,邏輯關鍵字,mysql注悉,注意下圖可以看出重要的是“'”,“ ”

ps:空格字符的變種有:“%20”,“\n”,“\r”,“\r\n”,“\n\r”,“chr(“32″)” 這也是為什麼mysql_escape_string()和mysql_real_escape_string() 兩個函數轉義“\n”,“\r”。其實很多phper只知道轉義\n,\r而不知原因,在mysql解析\n,\r時把它們當成空格處理,筆者測試驗證過,這裡就不貼代碼了。

(2)“and”,“or”,“\”,“#”,“– ”

邏輯關鍵可以組合很多注入代碼;mysql注悉則把固有sql代碼後面的字符全部給注悉掉從而讓注入後的sql語句能正常運行;“\”也是能組合很多注入字符\x00,\x1a。

ps:sql解析“#”,“– ”是大多數mysql防注入代碼沒有考慮到的,也是很多phper忽略。還有因為一些phper給參數賦值的時候會有用“-”來隔開,所以筆者建議不要這樣寫參數,當然也可以再過濾參數的時候“– ”(注意有空格的,沒空格不解析為注悉)當一個整體過濾而不是過濾“-” ,這樣就避免過多過濾參數。

(3)“null”,“%”,“_”

這幾個不能獨立,都不要在特定情況下,比如通配字符“%,_”都要在mysql like子句的前提下。所以“%”,“_”的過濾一般在搜索相關才過濾,不能把它們納入通常過濾隊列,因為有些如郵箱就可以有”_”字符

(4)關鍵字“select|insert|update|delete|*|union|join|into|load_file|outfile”

也許你會問怎麼這些重要關鍵字卻優先級這麼低。筆者想說的是因為這些關鍵字在沒有“'”,“””,“ ”,“and”,“or”等情況下購不成傷害。換句話說這些關鍵字不夠“獨立”,“依賴性”特別大。當然優先級低,不代表不要過濾。


3.3.3防注入代碼。

(1)參數是數字直接用intval()函數

注意:現在很多網上流行的防注入代碼都只是只是用addslashes()、mysql_escape_string()、mysql_real_escape_string()或三者任意組合過濾,但phper以為過濾了,一不小心一樣有漏洞,那就是在參數為數字的時候:
復制代碼 代碼如下:$id = addslashes($_POST['id']); //正確是$id = intval($_POST['id']); 
$sql =" select * from phpben.com where id =$id"; 
$sql =" select * from phpben.com where id =1 or 1=1";
對比容易發現,post過來的數據通過addslashes過濾後的確很多注入已經不起作用,但是$id並沒有intval,導致漏洞的存在,這是個小細節,不小心則導致漏洞。

(2)對於非文本參數的過濾

文本參數是指標題、留言、內容等可能有“'”,“'”等內容,過濾時不可能全部轉義或代替。

但非文本數據可以。
復制代碼 代碼如下:
function _str_replace($str ) 

     $str = str_replace(" ","",$str); 
     $str = str_replace("\n","",$str); 
     $str = str_replace("\r","",$str); 
     $str = str_replace("'","",$str); 
     $str = str_replace('"',"",$str); 
     $str = str_replace("or","",$str); 
     $str = str_replace("and","",$str); 
     $str = str_replace("#","",$str); 
     $str = str_replace("\\","",$str); 
     $str = str_replace("-- ","",$str); 
     $str = str_replace("null","",$str); 
     $str = str_replace("%","",$str); 
     //$str = str_replace("_","",$str); 
     $str = str_replace(">","",$str); 
     $str = str_replace("<","",$str); 
     $str = str_replace("=","",$str); 
     $str = str_replace("char","",$str); 
     $str = str_replace("declare","",$str); 
     $str = str_replace("select","",$str); 
     $str = str_replace("create","",$str); 
     $str = str_replace("delete","",$str); 
     $str = str_replace("insert","",$str); 
     $str = str_replace("execute","",$str); 
     $str = str_replace("update","",$str); 
     $str = str_replace("count","",$str); 
     return $str; 
}

ps:還有一些從列表頁操作過來的一般href是”phpben.php?action=delete&id=1”,這時候就注意啦,_str_replace($_GET['action'])會把參數過濾掉,筆者一般不用敏感關鍵作為參數,比如delete會寫成del,update寫成edite,只要不影響可讀性即可;

還有上面代碼過濾下劃線的筆者注悉掉了,因為有些參數可以使用下劃線,自己權衡怎麼過濾;

有些代碼把關鍵字當重點過濾對象,其實關鍵字的str_replace很容易“蒙過關”,str_replace(“ininsertsert”)過濾後的字符還是insert,所以關鍵的是其他字符而不是mysql關鍵字。

(3)文本數據防注入代碼。

文本參數是指標題、留言、內容等這些數據不可能也用str_replace()過濾掉,這樣就導致數據的完整性,這是很不可取的。

代碼:
復制代碼 代碼如下:
function no_inject($str) 


         if(is_array($str)) 
         { 
                   foreach($str as $key =>$val) 
                   { 
                           $str[$key]=no_inject($val); 
                   } 
         }else 
         { 
                   $str = str_replace(" "," ",$str); 
                   $str = str_replace("\\","\",$str); 
                   $str = str_replace("'","'",$str); 
                   $str = str_replace('"',""",$str); 
                   $str = str_replace("or","or",$str); 
                   $str = str_replace("and","and",$str); 
                   $str = str_replace("#","#",$str); 
                   $str = str_replace("-- ","-- ",$str); 
                   $str = str_replace("null","null",$str); 
                   $str = str_replace("%","%",$str); 
                   //$str = str_replace("_","",$str); 
                   $str = str_replace(">",">",$str); 
                   $str = str_replace("<","<",$str); 
                   $str = str_replace("=","=",$str); 
                   $str = str_replace("char","char",$str);   
                   $str = str_replace("declare","declare",$str); 
                   $str = str_replace("select","select",$str); 
                  $str = str_replace("create","create",$str); 
                  $str = str_replace("delete","delete",$str); 
                  $str = str_replace("insert","insert",$str); 
                 $str = str_replace("execute","execute",$str); 
                 $str = str_replace("update","update",$str); 
                 $str = str_replace("count","count",$str); 
         } 
    return $str; 
}

(4)當然還有其他與addslashes、mysql_escape_string結合的代碼。

防注入的代碼其實來來去去都是那些組合,然後根據自己程序代碼變通,筆者這些代碼也是沒考慮全的,不如cookes、session、request都沒全過濾。重要是知道其中原理,為什麼過濾這些字符,字符有什麼危害。

4、防止xss攻擊

XSS:cross site script 跨站腳本,為什麼不叫css,為了不和div+css混淆。

4.1Xss攻擊過程:

(1)發現A站有xss漏洞。

(2)注入xss漏洞代碼。可以js代碼,木馬,腳本文件等等,這裡假如A站的benwin.php這個文件有漏洞。

(3)通過一些方法欺騙A站相關人員運行benwin.php,其中利用相關人員一些會員信息如cookies,權限等。

相關人員:

管理員(如貼吧版主),管理員一般有一定權限。目的是借用管理員的權限或進行提權,添或加管理員,或添加後門,或上傳木馬,或進一步滲透等相關操作。

A站會員:會員運行A站的benwin.php。目的一般是偷取會員在A站的信息資料。

方法:

1)       在A站發誘騙相關人到benwin.php的信息,比如網址,這種是本地誘騙

2)       在其他網站發誘騙信息或者發郵件等等信息。

一般通過偽裝網址騙取A站相關人員點擊進benwin.php

(4)第三步一般已經是一次xss攻擊,如果要更進一步攻擊,那不斷重復執行(2)、(3)步以達到目的。

簡單例說xss攻擊

代碼:benwin.php文件
復制代碼 代碼如下:
<html> 
<head> 
<title>簡單xss攻擊例子</title></head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<dody> 
<form action="phpben.com?user_name=<?php echo $user_name; ?>"> 
<input type="submit" value="提交" > 
</form> 
</body> 
</html>
當用戶名$user_name的值是“benwin” onSubmit=”alert(‘這是xss攻擊的例子');” class= “”(這裡)
復制代碼 代碼如下:
<form action="phpben.com?user_name=benwin" onSubmit="alert('這是xss攻擊的例子');" class= "" > 
<input type="submit" value="提交" > 
</form>
當提交表單的時候就會彈出提示框。

(1)     很明顯$user_name在保存進數據庫的時候沒有過濾xss字符(和防注入很像,這裡舉例說明)==>發現漏洞

(2)     構造xss代碼:benwin” onSubmit=”alert(‘這是xss攻擊的例子');” class= “” 傳入數據庫

(3)     騙相關人員進來點擊“提交”按鈕

4.2常見xss攻擊地方

(1)Js地方

復制代碼 代碼如下:
<script language="javascript"> 
var testname =" <?php echo $testname;?>"; 
</script>
$testname的值只要符合js閉合關系:“”;alert(“test xss “);”(以下同理)

(2)form表單裡面
復制代碼 代碼如下:
<input type="text" name="##" value="<?php echo $val; ?>" />

(3)a標簽
復制代碼 代碼如下:
<a href="benwin.php?id= <?php echo $id; ?>">a標簽可以隱藏xss攻擊</a>

(4)用得很多的img標簽
復制代碼 代碼如下:
<img src="<?php echo $picPath; ?>" />
甚至一些文本中插入整個img標簽並且用width、 height、css等隱藏的很隱蔽

(5)地址欄

總之,有輸出數據的地方,更准確的說是有輸出用戶提交的數據的地方,都有可能是XSS攻擊的地方。

4.3防XSS方法

防xss方法其實和防注入很相似,都是一些過濾、代替、實體化等方法

(1)過濾或移除特殊的Html標簽。

例如:< 、>、<,、> '、”、<script>、 <iframe> 、<,、>、"

(2)過濾觸發JavaScript 事件的標簽。例如 onload、onclick、onfocus、onblur、onmouseover等等。

(3)php一些相關函數,strip_tags()、htmlspecialchars()、htmlentities()等函數可以起作用

5、CSRF

CSRF跨站請求偽造cross site request forgery。

5.1簡單說明CSRF原理

(1)A登錄Site1(如現在網民常上的淘寶、微博、QQ等),產生一些信息,session、cookies等等,且一直保持沒退出。

(2)A再登錄Site2(如一些成人網等,至於怎麼跑到Site2,多數是Site通過些手段,郵件欺騙等),打開site2的浏覽器和打開site1的一樣,否則無效

(3)Site2站中偽造了Site1的http請求(如修改密碼,買東西,轉賬等),Site1的服務器誤以為A在site1的正常操作(因為同浏覽器且A還沒登出),然後就運行了請求,那麼csrf已成功操作。

csrf和xss很相似。xss也能偽造請求,csrf也能制造腳本。

偽造的請求可以很多方面,發郵件、改密碼、返回用戶信息、交易等等,所以相對與xss攻擊來說csrf危害更嚴重。

5.2防范方法。

對於phper

(1)嚴密操控執行入口

執行一些敏感操作比如改密碼這些操作前判斷請求來源,只有本站服務器發的請求才可以執行。判斷方法可以判斷ip來源。非本站服務器ip不會執行。

(2)本站有外鏈的話做些必要操作

一般site2的hacker會在site1(比如論壇裡)裡發欺騙連接,因為在site1誘騙的相關人員一般都登錄site1了,滿足csrf氣體條件之一。

如當你點擊QQ郵件裡面的長外鏈時候,回跳轉到一個頁面提示“有風險”之類,這樣不僅可以減低跳出率,一些不懂的人看到這樣的提示,若不是非必要而是處於好奇點擊的連接一般不會繼續點擊訪問;還有是QQ郵件正文裡的圖片在加載內容時是不加載圖片的,要點擊“顯示圖片”按鈕才顯示圖片,這裡一個原因之一就是避免攻擊。

當然對於用戶體驗來說這是不可取的,可以優化的是判斷到一些網址(如QQ本身網址)是安全直接可以顯示(不用提示),而可疑的才提示或禁止。

(3)防止csrf也可以用防xss的方法。

6、防盜鏈

盜鏈問題增加服務器的負擔。盜鏈就是盜鏈網站盜取被盜鏈網站資源來實現一些功能。盜鏈方面主要是圖片、視頻、以及其他資源下載文件。

方法:判斷ip,只有本站服務器才能使用站點資源,否則不能使用。

代碼:

(1)在Apache htaccess添加
復制代碼 代碼如下:
RewriteEngine on  
RewriteCond %{HTTP_REFERER} !^$ [NC] 
RewriteCond %{HTTP_REFERER} !phpben.com [NC] 
RewriteCond %{HTTP_REFERER} !google.com [NC]  
RewriteCond %{HTTP_REFERER} !baidu.com [NC]  
RewriteCond %{HTTP_REFERER} !zhuaxia.com [NC] 
RewriteRule .(jpg|gif|png|bmp|swf|jpeg) /image/replace.gif [R,NC,L] 
RewriteRule ^(.*)$ http:\/\/phpben.com\/image\/$1 [L]
這樣,凡是不是phpben.com google.com baidu.com zhuaxia.com 域名請求的都返回replace.gif代替返回


7、防CC攻擊

CC攻擊:是利用不斷對網站發送連接請求致使形成拒絕服務的目的。

詳細百度百科:http://baike.baidu.com/view/662394.htm

代碼:
復制代碼 代碼如下:
session_start(); 
$ll_nowtime = $timestamp ; 
if (session_is_registered('ll_lasttime')){ 
$ll_lasttime = $_SESSION['ll_lasttime']; 
$ll_times = $_SESSION['ll_times'] + 1; 
$_SESSION['ll_times'] = $ll_times; 
}else{ 
$ll_lasttime = $ll_nowtime; 
$ll_times = 1; 
$_SESSION['ll_times'] = $ll_times; 
$_SESSION['ll_lasttime'] = $ll_lasttime; 

if (($ll_nowtime - $ll_lasttime)<3){ 
if ($ll_times>=5){ 
header(sprintf("Location: %s",'http://127.0.0.1')); 
exit; 

}else{ 
$ll_times = 0; 
$_SESSION['ll_lasttime'] = $ll_nowtime; 
$_SESSION['ll_times'] = $ll_times; 
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved