.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-TOKEN
的 httponly
标志设置为 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 兼容。
我的项目需要运行客户要求的安全测试。
我使用 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-TOKEN
的 httponly
标志设置为 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 兼容。