在Cookie上面設定httpOnly和Secure Flag時的重點整理。首先先快速介紹這兩個flag是做甚麼用的.
設定這些flag可以讓Cookie有多一層防護,避免像XSS, Session hijacking之類的攻擊。
在Java裡,有兩個取得Cookie的地方…
- 從request.getCookies。這個方法回傳的Cookies,是來自於當下用戶端的請求(request)裡。(參考)
- 從request.getHeader(“Cookie”)。這個方法回傳的Cookie,是來自於伺服端上一次回傳(response)裡的Set-Cookie header。(參考)
Session Cookie是甚麼…
Session Cookie和Cookie最大的差別是Session Cookie是沒有expiry date的,通常是會話結束時也會一併刪除之。而有expiry date的通常我們給予他名稱persistent cookie。但不管是哪種名稱,其實至少只要知道Cookie是放在用戶端,session是放在伺服端,都是拿來記錄非常小量的資料使用的。
有時候會發現在用戶端讀到的Cookie值跟伺服端所看到的值不一樣,到底是怎麼一回事…?
模擬一下以下情境步驟:
- 用戶端的網頁會儲存了一個Cookie,其鍵為email,值為test@domain.com。
- 當用戶端第一次請求至伺服端時,從request.getCookies方法取email Cookie,其值出現是test;而用二個方法header Cookie拿到的則是空值。
- 伺服端為了安全,回傳時會將所有Cookie都帶上httpOnly和secure的flags。
- 此時網頁嘗試第二次請求,所帶的這個email cookie值依然為test@domain.com。
- 伺服端從request.getCookies方法所拿到的email Cookie值依然是test;而這次header Cookie拿到的值則也是test。
這樣的結果跟我們一開始預期的結果其實落差很大,因為預期在伺服端所看到的值應該要為test@domain.com。為何會有這種現象主要有幾個重點需要理解。
- Http Cookie如果version為0時,裏頭的value不能有at sign (小老鼠) (參考),這解釋為何email被截了一大半。如果set version為1時,則會有雙引號。
- Response header SET-COOKIE 改變了用戶端的email Cookie值為test,造成第二次在header Cookie拿到的結果也變成test。
- 如果在伺服端沒有這個SET-COOKIE的步驟,則第二次在header cookie拿到email Cookie值則是test@domain.com。
- 設定的httpOnly會造成用戶端(例如JavaScript)無法讀取這個cookie。
總結以上情境,處理Cookie的資安重點如下:
- 後端只對自己用到的session cookie (如JSSESSIONID)做httpOnly,不需含前端的cookies。
- 前端應該對一些敏感性的cookie資料做加密或編碼,且要避免特殊符號文字。
- 設定secure flag確保Cookies只能在https裡傳送。
httpOnly跟secure flag設定方法有很多種
以java為例:
1. Cookie Interface
Cookie cookie = getMyCookie("myCookieName"); cookie.setHttpOnly(true); cookie.setSecure(true); resp.addCookie(cookie);
2. Response header
String sessionid = request.getSession().getId(); response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; httpOnly; secure");
3. web.xml
<session-config> <cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config> </session-config>
4. Tomcat context.xml
<Context useHttpOnly="true"> ... </Context>
參考:
- https://www.owasp.org/index.php/HTTPOnly
- https://www.owasp.org/index.php/SecureFlag
- http://docs.oracle.com/javaee/1.2.1/api/javax/servlet/http/HttpServletRequest.html#getCookies%28%29
- https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
- https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/Cookie.html#setValue(java.lang.String)
- http://stackoverflow.com/questions/33412/how-do-you-configure-httponly-cookies-in-tomcat-java-webapps
- https://en.wikipedia.org/wiki/HTTP_cookie#Session_cookie
受益良多 thx