.htaccess header 编辑 set-cookie 不适用于 laravel

.htaccess header edit set-cookie not work with laravel

我的项目需要运行客户要求的安全测试。

我使用 OWASP ZAP 运行 测试。

它会返回 cookie No HttpOnly Flag 警告,这是因为 "X-XSRF TOKEN" cookie 没有设置 httponly 标志。

我做了一些研究,我知道这个 cookie 没有为 javascript 像 axios 这样的库设置 httponly 来使用它。

但我使用laravel 5.5,在最初的项目中,有一个很好的机制让javascript库获得这个令牌而不直接操作cookie,通过元标志:

......

// layout.blade.php 
 <!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">

......

并在 index.js 中:

/**
 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.
 */

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

所以即使 XSRF-TOKENhttponly 标志设置为 true 也应该可以正常工作。

我跟踪 src 代码,发现我可以只修改一行使其工作。 somenoe 已经在 github 上公开了一个 pr 来解决这个问题:

https://github.com/ametad/framework/commit/2241b020ae3001ce5dabc1b7c5ea1514ff7f2e33

但我不敢随意修改框架的源代码, 所以我尝试通过 apache 服务器修改 cookie header(通过 public/.httaccess

# public/.httaccess
<ifModule mod_headers.c>
    Header always edit Set-Cookie: (.*) ", httponly"
    Header set X-Content-Type-Options nosniff
    Header always append X-Frame-Options SAMEORIGIN
    Header set X-XSS-Protection "1; mode=block"
</ifModule>

Header always edit Set-Cookie: (.*) ", httponly" 对我不起作用。 这条线以下是所有工作,只是 set-cookie 不工作。

知道如何解决这个问题吗?

首先,通常没有必要让 XSRF-TOKEN 仅为 http。这个 cookie 是加密的(所有 Laravel cookie 都被加密)因此即使客户端确实可以访问它,它实际上也不包含任何有用的信息。

您可以用自己的中间件覆盖默认的 VerifyCsrfToken 中间件:


namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier {
    protected function addCookieToResponse($request, $response)
    {
        $config = config('session');
        $response->headers->setCookie(
            new Cookie(
                'XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
                $config['path'], $config['domain'], $config['secure'], $config['http_only'], false, $config['same_site'] ?? null
            )
        );
        return $response;
    }

}

然后您可以将 Http/Kernel.php 中的框架 VerifyCsrfToken 替换为您自己的覆盖框架。

这样做的缺点是,当您升级 Laravel 版本时,您需要确保覆盖的 class 仍与基础 class 兼容。