CSRF,Cross-Site Request Forgery,跨站請求偽造。當大部分人都著重在自動擋 XSS 和 SQL 注入時,「自動擋 CSRF」這件事才剛開始起步。
CSRF 是指,在另一個站上,想辦法讓另一個站做事情。例如,開無名幫你砍 Gmail 帳號,開站幫你把無名的私密相簿解鎖等等。總之,CSRF 即是「用受害者的身份去做事」。
因為是以受害者的身份去做事情,所以就可以以他的名,去做一些事情。例如說,瀏覽器大多是用 cookie 或 IP 位置來分辨誰是誰,所以只要能用別人的身份去做事,就能殺人於無形。
很簡單:
會提到第二點,是因為,大部分瀏覽器都實作了 CORS,導致在做 GET 以外的請求時,都會驗證。在參數設定正確的狀況下,這會使得 CSRF 困難上許多。(但仍然不能扣除可以把驗證方式幹走的問題)
註:CORS 並不是每個非 GET 的請求都會生效,請參考上述 Mozilla 的說明文件。
不管 Cookie 有沒有設定 httpOnly
,在每次請求時,都會全部一起帶過去。所以,一個請求帶有 Cookie,但這不一定代表說,使用者真的發出這個請求了。有一種防範方式是用 JS 等等方式,計算認證用的 token,然後傳過去。
OWASP Cheat Sheet 中也提到:
Origin
或 Target
CORS Token
,上述用頁面中資料當作 token 的就是指這個可以看看 OWASP 的頁面。
不曉得 CVE 怎麼突然會有那麼長的 # 號。想必不是因為 2017 年有一百萬個 CVE?(因為 CVE 總共也才不到十萬個條目)
phpMyAdmin 是一個開源的 MySQL/MariaDB 管理工具。很明顯是用 PHP 寫的,然後這工具因為很久了,所以使用頗廣泛的。
phpMyAdmin 是可以讓人用網頁來管理資料庫的。在不用別的協定的狀況下,Web 前後端只能靠 HTTP POST/GET 等等來做溝通。
這個管理工具的一個功能是,可以使用 GET 請求來讀資料庫的功能,然後用 POST 請求來修改它,甚至還可以把資料表給刪了 (DROP table;
)。
不過,在 phpMyAdmin 中,如果直接把 POST 的東西轉成 GET Query,也是可以用 GET 來做刪資料表的動作的。
這就嚴重啦,因為這個連 CORS 也擋不住的。
雖然 phpMyAdmin 有放 token 在請求裡面,所以理論上:這攻擊只能在已經知道 token 的狀況下使用。但是,這次就算刪了 token,也還是會認證成功,然後一樣可以用 GET 刪資料表。
除了刪資料表以外,還可以建使用者,或如果有架 Wordpress 等等服務的話,可以直接在那個服務上新增使用者。畢竟,通常不會有人把預設 table 的名稱改掉的 :-)
前面有提到:phpMyAdmin 一部分的動作是用 GET,然後 phpMyAdmin 有實作 token,放在 body/URL 中。
回頭看一下 RFC 2616,HTTP 協定
4.3 Message Body
if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.
9.3 GET
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.
根據 HTTP 的規格,GET 理論上是不能帶 body 的,唯一帶參數過去的方法,就是帶在 query 參數裡面。雖然在開啟 HTTPS 的狀況下,只能知道目標主機的位置,但是:
所以,基本上,這個 token 的安全性是頗糟糕的。
前述提到,就算把請求 body 中的 token 給砍了,phpMyAdmin 還是可以用某種方式驗證。這代表說,頁面關了,還是可以傳這個請求。而且可以成功!
這個問題後來在 phpMyAdmin 4.7.7 之後修正了。作者說這個危害程度是中等,不過⋯⋯我的看法不同。
MySQL 有一個叫做 system
的指令,可以執行外部指令!
實際上,有什麼樣的能力,要視系統環境設定而定。所以,這個問題可大可小 :-)
作者有說,把 Query/Body 中的 token 拔掉,仍然能夠驗證。所以,這應該是一個 fallback 機制。當讀不到 token 時,就去讀 cookie。
但我好奇的是:反過來,讀不到 cookie 時,會發生什麼事?認證程序是否會兩邊都檢查?
如果不是的話,那我們目前眼前是一個很嚴重的 RCE 漏洞。
OWASP 只有說 PUT DELETE 和其他種 HTTP METHOD
可以透過 same-origin policy 來防止 CSRF
但這並不代表 same-origin policy 或者你說的CORS
可以防禦POST的CSRF攻擊
所以在 Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet
中的 General Recommendations For Automated CSRF Defense提到
We recommend two separate checks as your standard CSRF defense that does not require user intervention. This discussion ignores for the moment deliberately allowed cross origin requests (e.g., CORS). Your defenses will have to adjust for that if that is allowed.
1. Check standard headers to verify the request is same origin
2. AND Check CSRF token
Each of these is discussed next.
第二點還特別用大寫強調
還要檢查 CSRF token 才行
看了一下,CORS 有幾種狀況下不會觸發:
目前有瀏覽器中 Origin/Referer/Target 被竄改的實例嗎?