首先先快速介紹這兩個flag是做甚麼用的.
1. httpOnly : cookie無法被網頁的javascript讀取,只能被server端存取。
2. secure: cookie只能透過https加密傳送
簡單的說,設定這個讓cookie更安全,可以在XSS, Session hijacking之類的攻擊有多一層防護。
在Java裡,有兩個取得Cookie的地方
第一個是從request.getCookies。這裡取的Cookie是Client端當下request裡帶的所有cookies。(參考)
第二個是從request.getHeader("Cookie")。這裡取的Cookie是Server上一次設在Set-Cookie header裡的cookies。(參考)
Session Cookie是甚麼
session cookie和cookie最大的差別是session cookie是沒有expiry date的,通常是會話結束時也會一併刪除之。而有expiry date的通常我們給予他名稱persistent cookie。但不管是哪種名稱,其實至少只要知道cookie是放在client端,session是放在server端,都是拿來記錄非常小量的資料使用的。
有時候會發現在client端讀到的cookie值跟server端所看到的值不一樣,到底是怎麼一回事?
模擬一下以下情境步驟:
1. 網頁會記住一cookie其鍵為email值為test@domain.com。
2, 當傳送到server端時,從request.getCookies所拿到的email cookie值卻會是test;從header cookie拿到的值當然不意外的,是空值。
3. Server端為了安全,會將所有cookie都帶上httpOnly和secure flags
4. 網頁第二次嘗試傳送這個email cookie值依然為test@domain.com。
5. server端從request.getCookies所拿到的email cookie值還會是test;但header cookie拿到的值卻也是test。
這樣的結果跟我們一開始的預期的結果(test@domain.com)其實落差很大,主要有幾個重點需要理解。
1. Http Cookie如果version為0時,裏頭的value不能有at sign (小老鼠) (參考),這解釋為何email被截了一大半。如果set version為1時,則會有雙引號。
2. response header SET-COOKIE 改變了client端的email cookie值為test,造成第二次在header cookie拿到的結果也變成test。
3. 如果沒有server這個SET-COOKIE的步驟,則第二次在header cookie拿到的則會是完整的email值test@domain.com。
4. 設定的httpOnly會造成javascript無法讀取這個cookie。
總結以上情境,問題的癥結如下:
後端只對自己用到的session cookie (如JSSESSIONID)做httpOnly,不需含前端的cookies
前端應該對一些敏感性的cookie資料做加密或編碼,且要避免特殊符號文字
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