Web 開發(fā)常見安全問題

前端安全
XSS 漏洞
CSRF 漏洞

后端安全
SQL 注入漏洞
權限控制漏洞
SESSION 與 COOKIE
IP 地址
驗證碼

前言
水桶底部只要有一個洞,水就能全部流光。Web 安全同理。
前端安全
前端安全主要表現為通過瀏覽器間接影響到用戶數據的安全問題。
XSS 漏洞
XSS (Cross-Site Scripting),是一個我覺得耳熟能詳的前端安全問題。通過構造特殊數據,在用戶瀏覽器上執(zhí)行特定腳本,從而造成危害(如以用戶身份發(fā)帖、轉賬等)。
由于頁面內 JavaScript 幾乎可以完成各種事情,因此一旦網站上有 XSS 漏洞,那些沒有驗證碼等確認措施的操作大多都能不知情地完成,其危害甚大。
來看看幾個存在 XSS 漏洞的例子吧:
Case A: HTML DOM
<a href="/user/1">{{ user_name }}</a>

Exploit:
<script>alert(1)</script>

Result:
<a href="/user/1"><script>alert(1)</script></a>

最基本的例子,如果此處不對 user_name
中的特殊符號進行 escape,就會造成 XSS。

Case B: HTML Attribute
![]({{ image_url }})

Exploit:
" onerror="alert(1)

Result:
<img src="" onerror="alert(1)">

這個例子表明,如果只對尖括號進行 escape 是不夠的,很多時候引號也需要被 escape。簡單來說,對不同輸出場景,需要使用不同的 escape 規(guī)則。

Case C: JavaScript
<script>var user_data = {{ user_data|json_encode }};</script>

Exploit:
{"exploit": "</script><script>alert(1);//"}

Result:
<script>var user_data = {"exploit": "</script><script>alert(1);//"};</script>

這是一個特別的例子,大多數人覺得,對于輸出在 <script>
中的內容,json_encode
一下就安全了,其實不然。在這個例子中,XSS 仍然發(fā)生了。
更可怕的是,不少編輯器的代碼高亮方案中甚至無法看出上面的 Result 中存在 XSS 漏洞。如 Sublime Text 下,代碼高亮結果是這樣的,看上去沒有任何問題:


Sublime-Text-Highlight

但是瀏覽器解析出來的結果是這樣的:


Chrome-Inspector

解決方法:
在不同上下文中,使用合適的 escape 方式

不要相信 任何 來自用戶的輸入(不僅限于 POST Body,還包括 QueryString,甚至是 Headers)

CSRF 漏洞
CSRF (Cross-site request forgery),是一個知名度不如 XSS 但是卻同樣具有很大殺傷力的安全漏洞。它的殺傷力大正是因為很多開發(fā)者不知道這個漏洞。
舉個栗子,如果你網站 A 上的「登出」功能是這樣實現的:
<a >登出</a>

則存在 CSRF 漏洞。假設網站 B(當然也可以是網站 A 本身)中有這么一段代碼:


那么當用戶訪問的時候,就會導致網站 A 上的會話被登出。
需要注意的是,不只是 GET 類請求,POST 類請求同樣會存在 CSRF 漏洞,例如網站 B 中:
<form action="http://a.com/transaction" method="POST" id="hack"> <input type="hidden" name="to" value="hacker_account"> <input type="hidden" name="value" value="100000"></form><script>document.getElementById("hack").submit();</script>

那么用戶訪問網站 B 的時候,便會自動攜帶 A 的 SESSION 信息,成功 POST /transaction
到網站 A。
這個漏洞危害很大,例如以前某些 BTC 交易所就存在這個漏洞,一旦用戶被誘騙訪問了黑客精心布置的網站就會造成資金損失;又例如,以前某中國著名社交網站也存在這個漏洞,更糟糕的是該網站還允許用戶遞交自己的 <img>
顯示在所有人的信息流中,且某些傳播性操作可以用 GET

方式達成,這就導致黑客可以進行病毒式擴散,當然,僅僅是把

嵌入信息流也是有足夠大殺傷力的 :)
解決方法:
給所有請求加上 token 檢查。token 一般是隨機字符串,只需確保其不可預測性即可。token 可以在 QueryString、POST body 甚至是 Custom Header 里,但千萬不能在 Cookies 里。

檢查 referer
(請注意,這往往不能防御來自網站自身的 CSRF 攻擊,如用戶評論中的 <img>
就是一個常見觸發(fā)點)

后端安全
在這里,后端安全指的是對服務器數據等可能造成直接影響的安全問題。黑客一般會直接構造數據進行攻擊。
SQL 注入漏洞
SQL 注入漏洞應該也是一個大多數開發(fā)者都知道的漏洞。
考察以下 PHP 代碼:
<?php$user = mysql_query('SELECT * FROM USERS WHERE UserName="'.$_GET['user'].'"');

那么當請求中 user 參數為 ";DROP TABLE USERS;--
時,合成的 SQL 語句是:
SELECT * FROM USERS WHERE UserName="";DROP TABLE USERS;--"

這里產生什么結果就不需要解釋了吧 :) 另外,通過 SQL 注入,往往還能拿到系統(tǒng)權限。
解決方法:
所有 SQL 語句都使用參數化查詢(推薦)或對參數進行 escape(不推薦)

權限控制漏洞
這個就不仔細展開了,未經授權可以進行的操作都是權限控制漏洞。
例如,某些網站的后臺操作就仗著「以為用戶不知道入口地址」不進行任何權限檢查,又例如,某些操作可能出現不允許更改的字段被用戶遞交更改(往往是那些網頁上標記為 disabled
或者 hidden
的字段),再例如,允許通過 ../
訪問到不應該被訪問的文件等(一般存在于 include
中)。
解決方法:
所有地方都要進行權限檢查(如是否已登錄、當前用戶是否有足夠權限、該項是否可修改等),總之,不要相信任何來自用戶的數據,URL 當然也是。

SESSION 與 COOKIE
Session 和 Cookie 是兩種用于存儲用戶當前狀態(tài)的工具。某些開發(fā)者不了解 Session 與 Cookie 的區(qū)別,誤用或者混用,導致敏感信息泄露或者信息篡改。
Cookie 存儲在瀏覽器上,用戶可以查看和修改 Cookie。Session 是存儲在服務端的數據,一般來說安全可靠;大多數 Session 都是基于 Cookie 實現的(在 Cookie 中存儲一串 SESSION_ID,在服務器上存儲該 SESSION_ID 對應的內容)。

IP 地址
首先,用戶的 IP 地址一般存儲在 REMOTE_ADDR
中,這是唯一的可信的 IP 地址數據(視不同語言而定)。然后某些代理服務器,會將用戶的真實 IP 地址附加在 header 的 VIA
或 X_FORWARDED_FOR
中(因為REMOTE_ADDR
是代理服務器自身的 IP)。所以,要獲取用戶 IP 地址,一般做法是,判斷是否存在 VIA
或者 X_FORWARDED_FOR
頭,如果存在,則使用它們,如果不存在則使用 REMOTE_ADDR
。這也是網上大多數所謂教程提供的方法。
這就產生問題了,X_FORWARDED_FOR
或 VIA
是 HTTP Header,換句話說,它們是可以被偽造的。例如,在投票中,如果采信了 X_FORWARDED_FOR
,往往意味著被刷票。
解決方法:
只使用 REMOTE_ADDR
作為獲取 IP 的手段。

驗證碼
驗證碼里常見的問題有:非一次性、容易被識別。
非一次性指的是,同一個驗證碼可以一直被用下去。一般來說,每進行一次驗證碼校對(無論正確與否),都應該強制更換或清除 Session 中的驗證碼。
關于識別問題,在當前科技水平下,不加噪點不加扭曲的驗證碼幾乎是 100% 可識別的。所以大家自己看著辦吧…

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容