HTTP redirection in midst of a HTTPS context
How to reproduce : set your firefox browser with dom.security.https_only_mode=true
As a result you'll get stopped : 1/after login 2/after editing a page or settings or enabling a mod with the error "NS_ERROR_REDIRECT_LOOP".
If you check that line you can see that, yes. A http request is made - even out of a HTTPS context.
I cannot reproduce this, neither on one of my own wikis nor https://www.dokuwiki.org/ . Login and editing work with HTTPS only.
(note : The problem only occurred on successful logins)
Could it be a combination of my nginx settings & dokuwiki ?
I can give you a "default dokuwiki" that I'd just pasted on my webserver if it can help pinpoint the issue (maybe not, I'm still trying to cope with the fact you couldn't reproduce it :<) https://t2.arzinfo.eu.org/doku.php?id=start
I can reproduce your error on your https://t2.arzinfo.eu.org/doku.php?id=start I doubt that this is a bug in DW. Also, I'd rather not suspect nginx.
Does your setup involve a proxy? What's your DW baseurl setting?
But even then I wonder whether something else is going on since the error is a redirection loop. Also, your server even sends a Strict-Transport-Security: max-age=31536000; includeSubdomains; preload header for each request, so my understanding is that a browser should not even try to access http://….
my understanding is that a browser should not even try to access http://…
Yes, at least, that's what I was trying to go for.
Does your setup involve a proxy?
No proxy.
What's your DW baseurl setting?
I defined no baseurl - but I just tried to set it up, and it seem to fix the problem when set.
Now, I still believe it's a bit of an issue in the basurl guessing but as nobody beside me seem to be able to replicate it, it looks very niche.
For "if anyone fall on the same thing and do some connection I don't" here's an extract of my nginx config
add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; script-src 'self'; img-src 'self' data:; style-src 'self'; form-act>
add_header X-XSS-Protection "1; mode=block";
add_header Feature-Policy "geolocation none;midi none;notifications none;push none;sync-xhr none;microphone none;camera none;magnetometer no>
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css 14d;
application/javascript off;
~image/ max;
}
server {
listen 443 ssl http2;
server_name xxx.xxx;
##SSL
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305';
ssl_ecdh_curve secp384r1;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;
add_header X-Frame-Options deny;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; style-src >
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "no-referrer";
#add_header Feature-Policy "geolocation none;midi none;notifications none;push none;sync-xhr none;microphone none;camera none;magnetometer n>
#add_header Permission-Policy "geolocation=(none),midi=(none),notifications=(none),push=(none),sync-xhr=(none),microphone=(none),camera=(non>
add_header Permissions-Policy "geolocation=(self), microphone=()";
##php
location ~ \.php {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# A handy function that became available in 0.7.31 that breaks down
# The path information based on the provided regex expression
# This is handy for requests such as file.php/some/paths/here/
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
}
include snippets/ssl_credentials.conf;
client_max_body_size 42M;
root /srv/$subdomain;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
It seems the HTTPS environment variable isn't set. Which is curious. I guess we could also check for the protocol in the REQUEST_URI...
https://github.com/dokuwiki/dokuwiki/blob/5719588d0f688f7f6046619e9d8a8df7aba77ef6/inc/init.php#L535-L547
Oh nice.
Looking at understanding the behavior better I tried to add some echo '<pre>'.print_r($_SERVER,true).'</pre>'; to the function.
Apparently the "is_ssl" is called 3 time on each page. The 3 $_SERVER output are exactly the same (I used diff to check).
Also neither -HTTP_X_FORWARDED_PROTO -HTTPS
Are ever set (I'm confused too ! Everything works https without any https flag ?)
Here is also the $SERVER difference between "normal POST request" and the after "pushing the send button while editing a dokuwiki" is this :
- [REQUEST_METHOD] => POST
+ [REQUEST_METHOD] => GET
- [REMOTE_PORT] => 40084
+ [REMOTE_PORT] => 10426
- [CONTENT_LENGTH] => 187
+ [CONTENT_LENGTH] =>
- [CONTENT_TYPE] => application/x-www-form-urlencoded
+ [CONTENT_TYPE] =>
- [HTTP_SEC_FETCH_USER] => ?1
- [HTTP_ORIGIN] => null
- [HTTP_CONTENT_LENGTH] => 187
- [HTTP_CONTENT_TYPE] => application/x-www-form-urlencoded
Also because nothing changes for is_ssl check, that condition is the one that triggers every time and return "false"
if (preg_match('/^(|off|false|disabled)$/i', $_SERVER['HTTPS'] ?? 'off')) {
return false;
}