前言
安全這種東西就是不發生則已,一發生則驚人。作為前端,平時對這方面的知識沒啥研究,最近了解了下,特此沉淀。文章內容包括以下幾個典型的 web 安全知識點:XSS、CSRF、點擊劫持、SQL 注入和上傳問題等(下文以小王代指攻擊者),話不多說,我們直接開車🚗(附帶的例子淺顯易懂哦😯)。
XSS(Cross-site scripting)
XSS 中文叫做跨站腳本攻擊。
一句話解釋:小王在網頁中注入惡意代碼,當用戶訪問頁面時,代碼會自動運行。
具體點說:凡是在頁面中可輸入的地方(如地址欄、搜索框和評論區等等)都有隱藏的風險,小王可以在這些地方輸入一些特殊的代碼(形如 <script>alert(1)</script>
),于是乎本來只是單純的文本變成了可執行的代碼,從而造成了攻擊。你可能會覺得 alert(1)
能有多大點事,但把它換成別的威力就不一樣了,它可以重定向到一個由小王控制的頁面、冒充用戶發送請求、竊取用戶信息發送到小王的服務器上等等。當然了,這還不夠具體,例子才是最直白的👇。
舉個栗子
因為 XSS 攻擊有反射型、存儲型和 DOM 型三種類型,所以我們每種都舉個簡單的栗子🌰:
反射型
反射型 XSS 主要有以下兩個步驟:
- 假設我們訪問一個
www.a.com/?name=hh
頁面,后端會把其中的name
參數取出來并拼接到 html 中(形如<p>你好啊,hh</p>
)返回給用戶。 - 這時如果我們訪問
www.a.com/?name=hh<script>alert(1)</script>
頁面,此時后端會返回形如<p>你好啊,hh<script>alert(1)</script></p>
這樣的一個 html,其中的 script 腳本就會在我們的瀏覽器上加載執行,從而造成攻擊。
你可能會覺得這種 url 看起來就有嫌疑,我們一般不訪問,但如果把這個 url 轉成一個短網址(所謂短網址就是把 url 轉成一個 看起來簡約又正常的鏈接),并在網上散播(通常伴隨一些美女圖片、外掛和金錢💰等一些具有誘惑力的內容),從而騙取用戶點擊這個 url,造成攻擊。所以日常生活中不要亂掃二維碼、亂點鏈接。
當然了,拼接的形式多種多樣:
拼接前 | 拼接字符串 | 拼接后 |
---|---|---|
<div>#{msg}</div> | <script>alert(1)</script> | <div><script>alert(1)</script></div> |
<img src="#{image}" /> | 1" onerror="alert(1) | <img src="1" onerror="alert(1)" /> |
var data = "#{data}" | hello";alert(1);" | var data = "hello";alert(1);"" |
存儲型
這種類型一般出現在評論區、論壇、留言等類似的地方,基本流程是小王提交了一個惡意評論(就是包含一些惡意代碼,和上面類似,形如這樣的評論 <img src="1" onerror="alert(1)" />
),只不過該評論被保存到了數據庫中,而評論對大家又都是可見的,所以任何用戶訪問該頁面時,惡意代碼就會從數據庫中取出,拼接在 html 中返回給用戶,頁面加載評論的同時也執行了其中的惡意代碼。與反射型相比,存儲型的輻射范圍更加廣泛,處理起來也較為麻煩,有時還需要查好多庫刪好幾張表。
DOM 型
典型的例子就是你連接了一個公共 wifi,瀏覽頁面的時候在底部或者四周有時會有一些小廣告的出現,因為這種網絡劫持會動態修改頁面的內容,比如在 html 中追加一些廣告或暗鏈(暗鏈就是偷偷加入幾個 a 標簽,一般可用來增加搜索排名),要注意的是這種攻擊是不涉及到服務器的,它的核心是動態修改 dom。
小小總結
總的來說就是頁面可輸入或拼接顯示的地方就可能會有潛在的風險。我們演示個小的 demo,雖然實際上不是這樣的😂,但意思到了: 當我們第一次輸入
<script>alert(1)</script>
的時候,alert
不生效是因為 H5 中規定用 innerHTML
插入的 script 將不被執行,但是我們可以寫別的,比如 <img src='x' onerror="alert(1)">
,此時 alert 就被執行了,這個在 MDN 上有明確的說明,這里給大家截圖看一下👀: 作為前端平時要注意 innerHTML 等一些有字符串拼接并展示的地方。
防御措施
轉義和過濾:
一般來可以使用編碼或轉義的方式來防御 XSS 攻擊,就像下面這樣:
function escape(str) {if (!str) return ''str = str.replace(/&/g, '&')str = str.replace(/</g, '<')str = str.replace(/>/g, '>')str = str.replace(/"/g, '"')str = str.replace(/'/g, ''')return str
}
對于富文本內容,因為其需要保留 html,所以不好直接使用轉義的方法,通常使用白名單過濾(就是允許特定的 html 標簽和屬性),以抵御 XSS 攻擊。當然了更不要相信用戶的任何輸入,對用戶的輸入進行特殊字符(如尖括號)的檢查也是有必要的。
CSP(Content Security Policy)
這個其實就是設置個響應頭信息(Content-Security-Policy
),告訴瀏覽器哪些資源是可加載執行的(實質就是白名單制度),為對應的內容指定相應的策略。具體設置大家可以查閱 MDN,這里截個 github 的圖作為示例: 或者加個 meta 標簽:
<meta http-equiv="Content-Security-Policy" content="img-src 'self';">
其他
- HttpOnly:禁止 js 讀取 cookie
- 限制輸入內容長度:提高門檻
- 敏感操作使用驗證碼
CSRF(Cross-site request forgery)
CSRF 中文叫做跨站請求偽造。 一句話解釋:小王盜用你的身份,以你的名義發送惡意請求(發郵件、轉賬之類的)。
舉個栗子
這個沒有分類,所以我們直接上栗子🌰:
- 用戶登錄了 www.a.com,登錄態被保存在 cookie 中(這是前提)。
- 假設 www.a.com 頁面有個轉賬的功能,形如:
https://www.a.com/index.php?money=100&to=xx
,這個請求能夠把 100 塊轉到 xx 同學的賬戶上。 - 小王引誘用戶打開了 www.b.com 頁面,而這個頁面有一個形如
<img src="https://www.a.com/index.php?money=100&to=wo">
這樣的標簽,于是瀏覽器就會自動發起一個轉賬請求,并且這個請求會攜帶上 a 網站的 cookie(即便這個標簽根本不在 www.a.com 內),所以能請求成功。 - 用戶并不曉得,這很可怕😱。所以有些網站會要求已登錄的用戶在一些關鍵步驟時再次輸入密碼就有一定道理了。
防御措施
CSRF 攻擊通常有以下兩個特點:
- 通常發生在第三方網站。
- 小王并不能獲取到 cookie,他只是借用請求,有點借刀殺人的意思。
針對以上兩點我們可以有以下幾種預防措施:
referer
因為請求頭中的 referer 記錄了請求的來源地址,referer 會指向 b 網站,所以我們可以對 referer 進行檢測,以此來禁止來自第三方網站的請求。 但每個瀏覽器對于 referer 的具體實現可能有差別,也不能保證瀏覽器自身沒有安全漏洞。在有些情況下,攻擊者甚至可以隱藏、修改自己請求的 referer。另外 origin 也是一樣的道理(origin 只包含了域名信息,不包括具體的 url 路徑)
token
由于 CSRF 是利用了瀏覽器自動攜帶 cookie 的特性,所以我們可以多加一個校驗的字段(不通過 cookie 傳遞),簡單點說就是:
- 登錄的時候服務端會返回一個 token 值給前端。
- 前端在發送請求的時候再把這個 token 當作請求數據傳遞或者放在請求頭里。
- 后端會對這個 token 值進行校驗。而由 CSRF 的請求是沒有攜帶 token 的,所以不會成功。
至于 token 是啥,這里簡單說明以下,其實它是個字符串,你可以當做個臨時 id,一般由 userId、隨機數、時間戳通過散列算法得到(形如:let token = md5('userId' + 'time' + 'Math.random() + '...')
,其實就是調用一個函數)。
加驗證碼
加驗證碼的本質和 token 是一樣的,這兩種類型的原理都是在 cookie 之外的某個地方多增加一個字段供后端校驗,這里增加的字段就是驗證碼。這樣一來第三方只能攜帶上 cookie 但是帶不上這個驗證碼字段,也就預防了 csrf 攻擊。
SameSite
可以通過設置 SameSite 的值來禁止第三方網站攜帶 cookie。SameSite 有三個值可以設置:Strict、Lax、None。具體作用如下:
- Strict:完全禁止第三方 cookie,跨站點時,任何情況下都不會發送 cookie。
- Lax:大多數情況也是不發送第三方 cookie,但是導航到目標網址的 get 請求除外。Chrome 計劃將 Lax 變為默認設置。
- None:可以顯式關閉 SameSite 屬性,不過必須同時設置 Secure 屬性,因為 cookie 只能通過 https 協議發送),否則無效。 大概這樣設置:
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
點擊劫持
這個比較好理解,我們直接看例子: 其實就是通過覆蓋不可見的頁面,誘導用戶點擊而造成的攻擊行為。稍微高級一點的偽裝可以怎么樣呢,就是做成一個游戲界面,讓你在頁面上狂點,而實際上呢,則會觸發一些攻擊事件,比如打開攝像頭、發送郵件之類的。至于我們為什么會點擊,因為騙子通常知道你想要什么😎,好奇心也驅使你這樣做,并且我們當時并不覺得會有什么危險,所以我們都愿意試試看。
防御措施
禁止內嵌 iframe
讓自己的網站不要被目標網站內嵌,可以通過 js 和設置頭部 X-Frame-Options 實現:
if (top.location !== window.location) top.location = window.location
setHeader('X-Frame-Options', 'DENY')
驗證碼
增加攻擊成本。
SQL 注入
因為這個和 XSS 有點小像,所以在這里稍微提及一下😯。
一句話解釋:小王利用潛在的數據庫漏洞訪問或修改數據。
舉個栗子
- 用戶填寫了用戶名和密碼,點擊登錄發送了一個請求。
- 后端接收到請求并解析參數,將其拼裝成一個 SQL 語句執行,形如
select * from user where username = '${data.username}' and pwd='${data.pwd}'
,并返回登錄成功。 - 結果小王在填寫密碼的時候寫上了
1' or '1'='1
,結果后端一拼接 SQL 語句就變成了select * from user where username = 'xiaowang' and pwd = '1' or '1'='1'
,顯然這是成立的,也會返回成功。
是不是和 XSS 的拼接漏洞很像呢,本來是數據的東西變成程序執行了。
防御措施
以下內容可跳過,僅作為了解:
- 不要給出具體的錯誤信息,越具體越給了小王方向
- 檢查數據類型
- 對數據進行轉義
- 使用參數化查詢:相當于分成兩條語句,第一步明確目的,不能再被修改;第二步不管傳啥只當作數據處理
- 使用 ORM(對象關系映射):就是可以不用拼 SQL 語句的意思
上傳問題
一句話解釋:上傳的文件被當做程序解析執行。
舉個栗子
- 小王上傳了一個惡意文件 xx.php,內容如下:
<?phpphpinfo();
?>
- 如果我們點擊該文件的下載鏈接,就會執行該 php 文件(前提是服務器可以解析 php 文件,并且文件所在目錄要有執行的權限)。
防御措施
- 限制上傳后綴
if (ext === 'js') throw new Error('xxx')
- 文件類型檢測
if (file.type !== 'images/png') throw new Error('xxx')
- 檢查文件內容以什么開頭
- 程序輸出:就是不運行,有個讀寫的過程
- 權限控制:可寫可執行互斥原則
DoS 攻擊
DoS(Denial of Service)攻擊就是利用合理的服務請求來占用過多的服務資源,從而使得合法用戶無法得到服務的響應。比如 SYNflood 攻擊、IP 欺騙、帶寬DoS攻擊、塞滿服務器的硬盤等攻擊手段,這個作為了解就行,具體可自行百度。
其他相關措施
主要都是提高攻擊門檻:
- 明文變換成密文,雖然我們很多密碼明文都是一樣的,但不同網站的密文一般是不一樣的
- https 傳輸
- 頻率限制
- 驗證碼
總結
沒有絕對安全的網站,我們要做的就是提高攻擊成本,問題的關鍵也不在于小王能不能破譯,而是值不值得,畢竟付出與收獲不成正比,誰愿意倒貼呢?🙌
CSDN大禮包:《黑客&網絡安全入門&進階學習資源包》免費分享🎁
😝朋友們如果有需要全套《黑客&網絡安全入門&進階學習資源包》,可以掃描下方二維碼免費領取
點擊鏈接也可直接獲取 CSDN大禮包:《黑客&網絡安全入門&進階學習資源包》免費分享
1??零基礎入門
① 學習路線
對于從來沒有接觸過網絡安全的同學,我們幫你準備了詳細的學習成長路線圖。可以說是最科學最系統的學習路線,大家跟著這個大的方向學習準沒問題。
② 路線對應學習視頻
同時每個成長路線對應的板塊都有配套的視頻提供:
因篇幅有限,僅展示部分資料
2??視頻配套資料&國內外網安書籍、文檔
① 文檔和書籍資料
② 黑客技術
因篇幅有限,僅展示部分資料
3??網絡安全源碼合集+工具包
4??網絡安全面試題
上述所有資料 ?? ,朋友們如果有需要全套 📦《網絡安全入門+進階學習資源包》,可以掃描下方二維碼免費領取 🆓
點擊鏈接也可直接獲取 CSDN大禮包:《黑客&網絡安全入門&進階學習資源包》免費分享