網頁

Tips in Set Cookie with httpOnly and Secure flag

在Cookie上面設定httpOnly和Secure Flag時的重點整理。

首先先快速介紹這兩個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