資安議題 -- Cookies

前言

cookie可以讓網頁帶有狀態性,達到Session 管理、個人化、追蹤的功能,cookie是面向客戶端,儲存在瀏覽器裡面。

cookie由伺服器端設置後放到response的header裡,瀏覽器取得後放入儲存cookie的地方,向伺服器發送request時,會將存放的cookie放入request的header中。

javascript設置的cookie不能帶有安全性標誌,如Secure、HttpOnly、SameSite。

設置Cookie

設置cookie的方式有兩種:

  • 使用伺服器設定 cookie,通過 response 的 Set-Cookie header,瀏覽器會根據 Set-Cookie 儲存 cookie。
  • 使用客戶端的 javascript 設定 cookie,例如:document.cookie = "name=John;"。

Cookie flag

Expires

設定一個日期,到日期時就會自動失效。

Max-Age

設定秒數,秒數過後自動失效,比Expires優先度高。

Domain

設定作用網域,設定之後會包含子網域,若無設定則默認當前網域,不包含子網域。

Path

設定作用路徑,設定/admin將匹配/admin/users,/admin/roles等路徑。

Secure

只能使用https傳到伺服器。

HttpOnly

只能經由伺服器存取cookie,不能經由document.cookie。

SameSite

cookie不能跨域發送。

cookie行為

1. 當server設定cookie,會在response的header加入Set-Cookie告知瀏覽器,瀏覽器會將cookie保存在瀏覽器中。

2. 設定完成後,request會帶著儲存的cookie去server。

response header的set cookie:


request header的cookie:



3. server端設定的cookie會帶有httponly,javascript無法讀取跟修改此類的cookie,若javascript先設定了id = 1,之後 server 設定了 id = 2,cookie將會被覆蓋並會被加上httponly,javascript就無法在讀取id的值。

4. 當使用者用瀏覽器去訪問網站,server可以藉由request取得由javascript設定的cookie,但若是使用框架( 如:laravel ),有些框架會去加密server設定的cookie,則request裡面javascript的cookie無法直接取得,因為cookie經過serve端已經加密,javascript設定的cookie會保留明文,如下圖。


javascript如下:



5. javascript無法設定httponly。

Laravel XSRF-TOKEN的問題

Set-Cookie: XSRF-TOKEN= << value >> ; expires=Tue, 22-Dec-2020 12:56:36 GMT; Max-Age=7200; path=/; samesite=lax;

可以發現這個cookie是由server設定的但卻沒有httponly,是因為在XSRF-TOKEN上加入httponly無法增加安全性上的優勢。

可以參考此處:https://security.stackexchange.com/questions/175536/does-a-csrf-cookie-need-to-be-httponly

但是資安檢查不會管你需不需要加,他只在乎有沒有加,所以就變成在laravel上的XSRF-TOKEN一定要有httponly。

解法如下:

在middleware裡面的 VerifyCsrfToken 重載 addCookieToResponse function,將 new Cookie 的最後一個參數設為true。

Symfony\Component\HttpFoundation\Cookie 的建構子參考:https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/HttpFoundation/Cookie.php

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
use Symfony\Component\HttpFoundation\Cookie;

class VerifyCsrfToken extends Middleware
{
    /**
     * Indicates whether the XSRF-TOKEN cookie should be set on the response.
     *
     * @var bool
     */
    protected $addHttpCookie = true;

    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
    ];

    protected function addCookieToResponse($request, $response)
    {
        $response->headers->setCookie(
            new Cookie('XSRF-TOKEN',
                $request->session()->token(),
                time() + 60 * 120,
                '/; samesite=strict',
                null,
                config('session.secure'),
                true)
        );

        return $response;
    }
}


留言

這個網誌中的熱門文章

WINDOWS cmd 操作:查看進程、TCP連線、刪除TCP連線和進程

mongodb aggregate 筆記

mongodb shell 操作