Good morning everyone,
I was already asking on Discord but got redirect to the forum instead.
I’m running into a small security issue where on an audit the cookie flag got revealed not being set to secure
.
Installed kirby version: 4.3.0
url() output: https://test-
Code to generate the cookie/session:
$session = $kirby->session();
$session->set('test', 10);
echo $session->get('test');
Cookie Flag in Chrome Dev Tools (also on Firefox):
Name: kirby_session
Value: ....
Domain: test-
Path: /
Expires: 2024-08-20T07:35:50.662Z
Size: 152
HttpOnly: Yes
Secure:
SameSite: Lax
As you can see the secure
flag isn’t set to true/secure.
Any ideas?
You can secure the session cookie in your php.ini
session.use_strict_mode = On
session.cookie_secure = On
session.use_only_cookies = On
session.cookie_httponly = On
Hello @texnixe,
I’m currently not able to modify the php.ini, but set it accordingly in index.php with init_set(…).
At least phpinfo(); outputs it correctly.
Unfortunately it still doesn’t get the secure flag.
I digged more into how kirby is creating a cookie/session for it.
Seems like that Uri::scheme() is not setting/getting “https” or “ssl” correctly. That’s why kirby_session wont be secure, even if I update the php.ini.
In the config I whitelisted all URLs (array) with http (localhost) and https (staging/production).
Any ideas?
Sorry for the delay. Looks like we missed your reply in August.
About php.ini
: The options @texnixe mentioned won’t take effect on sessions created by $kirby->session()
as Kirby does not use PHP’s built-in session handling. Sorry for the confusion.
You are right that the detected URI scheme comes from the environment and therefore from the config. In your first post you wrote that url()
correctly returns https://test-...
So the environment should be set up correctly.
To be sure, could you please still check what var_dump(Kirby\Http\Uri::current())
gives you? Please put that into a template temporarily and check the scheme property.
Hello Lukas
Thank you for your reply.
I used var_dump(Kirby\Http\Uri::current()->scheme());
in a template.
The output is https
.
OK, then the environment is correct. If you delete the session cookie in your browser and log in again, do you still get the missing Secure flag?
Yes. And I’m only using the csrf() helper for a form. Nothing besides that.
Hm, that suggests to me that it’s a deeper issue, like the web server or a (reverse) proxy modifying the response.
You can verify this by manually calling:
setcookie('test-cookie', 'some value', ['secure' => true]);
Alternatively you can temporarily place var_dump($options)
in this line in the Cookie
class to verify which values Kirby passes into PHP’s setcookie()
.
I was thinking about a reverse proxy aswell, let me know if I have to reach out to the sys admin for it.
manually calling setcookie does in fact set it secure
.
the output of the var_dump:
array(5) {
["lifetime"]=> int(1729240926)
["path"]=> string(1) "/"
["secure"]=> bool(false)
["httpOnly"]=> bool(true)
["sameSite"]=> string(3) "Lax"
}
Thanks for testing. That confirms that it’s not the server or reverse proxy, but something internal to Kirby or your site code.
In that var_dump()
output, secure
should be true
. If it was, the cookie would work just like the one you set manually for testing.
Since we already confirmed that Uri::current()->scheme()
is https
, it’s nothing obvious I can point to.
Do you have the means to debug this step by step? Here are the relevant code parts:
Hello Lukas
Yes, but might need some help:
Step 1:
Can’t get the output working.
Step 2:
public static function __callStatic(string $method, array $arguments)
{
var_dump('URL 1: _______ ' . ($arguments[0] ?? static::current()));
$uri = new Uri($arguments[0] ?? static::current());
var_dump('URL 1: _______ ' . $uri);
exit;
return $uri->$method(...array_slice($arguments, 1));
}
Output:
string(52) “URL 1: _______ http://domain.tld/de/test”
string(52) “URL 1: _______ http://domain.tld/de/test”
Step 3:
public static function toObject(string|null $url = null): Uri
{
var_dump('URL 2a: _____ ' . $url);
var_dump('URL 2b: _____ ' . Uri::current());
var_dump('URL 2c: _____ ' . new Uri($url));
return $url === null ? Uri::current() : new Uri($url);
}
Output:
string(14) "URL 2a: _____ "
string(51) “URL 2b: _____ http://domain.tld/de/test”
Seems like https wont be set correctly there?
I have no idea tbh.
You sure you can exclude the server?
Its hosted on azure cloud with a reverse proxy. If I move the whole setup to cyon (for example), its working perfectly.
At this point, to be honest I can’t. I’m afraid we cannot really help you with debugging this further because it really looks like a deeper setup issue.