fossar / selfoss

multipurpose rss reader, live stream, mashup, aggregation web application
https://selfoss.aditu.de
GNU General Public License v3.0
2.35k stars 343 forks source link

Authentication with multiple instances on the same server #1404

Open davidoskky opened 1 year ago

davidoskky commented 1 year ago

Quite a niche problem, but I'll point it out. I have a few different selfoss instances installed on a server for testing purposes. These are simply placed in different folders and thus you can access them by changing folder in the url. Logging into one instance also gives you access to the other ones and logging out from one logs you out from all of them. This happens even if the credentials to access the instances are different.

jtojnar commented 1 year ago

Right, we use the same session variable:

https://github.com/fossar/selfoss/blob/b4d6cf9a1e236bf8c92f1a8957acbc1362e49288/src/helpers/Authentication.php#L98

The session cookie can be limited to certain path. It applies to / by default but we should be setting it to a subdirectory so I would expect it to not be cross-contaminated:

https://github.com/fossar/selfoss/blob/b4d6cf9a1e236bf8c92f1a8957acbc1362e49288/src/helpers/Authentication.php#L41

If you set logger_level=DEBUG in your config.ini, what do you see in the log? There should be something like the following:

https://github.com/fossar/selfoss/blob/b4d6cf9a1e236bf8c92f1a8957acbc1362e49288/src/helpers/Authentication.php#L47

davidoskky commented 1 year ago

Does this mean that anyone with write access on the webserver can fabricate a cookie to obtain access?

Logs: Logging in from another instance:

[2023-01-26 09:39:51] selfoss.DEBUG: set cookie on */selfoss_test/ expiring in 2592000 seconds  
[2023-01-26 09:39:51] selfoss.DEBUG: session does not contain valid auth  
[2023-01-26 09:39:51] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/*/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} 
[2023-01-26 09:39:51] selfoss.DEBUG: Establishing SQLite database connection  
[2023-01-26 09:39:51] selfoss.DEBUG: set cookie on */selfoss_test/ expiring in 2592000 seconds  
[2023-01-26 09:39:51] selfoss.DEBUG: session does not contain valid auth  
[2023-01-26 09:39:51] selfoss.DEBUG: set cookie on */selfoss_test/ expiring in 2592000 seconds  
[2023-01-26 09:39:51] selfoss.DEBUG: session does not contain valid auth  
[2023-01-26 09:39:51] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/*/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} 
[2023-01-26 09:39:51] selfoss.DEBUG: Establishing SQLite database connection  

Logging in normally:

[2023-01-26 09:36:50] selfoss.DEBUG: set cookie on */selfoss_test/ expiring in 2592000 seconds  
[2023-01-26 09:36:50] selfoss.DEBUG: logged in using valid session  
[2023-01-26 09:36:50] selfoss.DEBUG: logged in with supplied username and password  
[2023-01-26 09:36:50] selfoss.DEBUG: set cookie on */selfoss_test/ expiring in 2592000 seconds  
[2023-01-26 09:36:50] selfoss.DEBUG: logged in using valid session  
[2023-01-26 09:36:50] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/*/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} 
[2023-01-26 09:36:50] selfoss.DEBUG: Establishing SQLite database connection  
davidoskky commented 1 year ago

I'll correct myself, access is not granted in any case. Logout always logs out from all instances. Log in instance 1, log out from instance 2, [instance 1 logged out], log in instance 2 -> access granted to instance 1 Log in instance 1, log out from instance 1, [instance 2 logged out], log in instance 2 -> access to instance 1 not granted

jtojnar commented 1 year ago

Does this mean that anyone with write access on the webserver can fabricate a cookie to obtain access?

The cookie contains a session ID so to fabricate the cookie, you would need to obtain the session ID. The session storage directory should be only available to the user the PHP server is running under. Normally, you would use separate php-fpm service running under a different user for each web app so that should not be an issue.

So unless someone can run programs under the same PHP user as your selfoss instance you should be safe. If that was allowed, they could just access database credentials directly, anyway.

jtojnar commented 1 year ago

I do not think anything have changed in this area but are you running latest snapshot or 2.19?

access is not granted in any case. Logout always logs out from all instances. Log in instance 1, log out from instance 2, [instance 1 logged out], log in instance 2 -> access granted to instance 1 Log in instance 1, log out from instance 1, [instance 2 logged out], log in instance 2 -> access to instance 1 not granted

Hmm, that does not make sense to me.

Just to confirm, the asterisk in your log is where you replaced the domain?

It is weird that both selfoss instances say “set cookie on */selfoss_test/”.

  1. What URLs do you use to access them? You can replace the domain with localhost or some other placeholder to anonymize it.
  2. What is the directory structure like? Is each instance in an independent subdirectory of the same root (e.g. /srv/http/my-domain) or is one instance nested inside the other?
  3. What web server do you use and how did you configure it? With Apache, do you use a single VirtualHost or multiple ones?
davidoskky commented 1 year ago

Both instances are running 2.19 I replaced the domain with *. These logs were both from the same instance, I'm using Apache and these instances are in the same virtualhost each in an independent subdirectory of the same root folder.

I'll provide more logs performing the two sequences, I start by clearing the cookies, during the procedure I had two cookies most of the passages.

Instance 1 ``` Log in instance 1 [2023-01-26 10:56:25] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:56:25] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:56:25] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 10:56:25] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 10:56:25] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:56:25] selfoss.DEBUG: logged in using valid session [2023-01-26 10:56:25] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:56:25] selfoss.DEBUG: Establishing SQLite database connection Log out of instance 2 [2023-01-26 10:57:52] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:57:52] selfoss.DEBUG: logged in using valid session [2023-01-26 10:57:52] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:57:52] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 10:57:52] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:57:52] selfoss.DEBUG: logged in using valid session Log in instance 2 [2023-01-26 10:59:26] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:59:26] selfoss.DEBUG: logged in using valid session [2023-01-26 10:59:26] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:59:26] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 10:59:27] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:59:27] selfoss.DEBUG: logged in using valid session [2023-01-26 10:59:27] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 10:59:27] selfoss.DEBUG: logged in using valid session [2023-01-26 10:59:27] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:59:27] selfoss.DEBUG: Establishing SQLite database connection Clear cookies and log in instance 1 [2023-01-26 11:02:45] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:02:45] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:02:45] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 11:02:45] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 11:02:45] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:02:45] selfoss.DEBUG: logged in using valid session [2023-01-26 11:02:45] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:02:45] selfoss.DEBUG: Establishing SQLite database connection Log out of instance 1 [2023-01-26 11:03:35] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:03:35] selfoss.DEBUG: logged in using valid session [2023-01-26 11:03:35] selfoss.DEBUG: logged out and destroyed session Log in instance 2 [2023-01-26 11:04:31] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:04:31] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:04:31] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:04:31] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 11:04:31] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:04:31] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:04:31] selfoss.DEBUG: set cookie on localhost/selfoss/ expiring in 2592000 seconds [2023-01-26 11:04:31] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:04:31] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:04:31] selfoss.DEBUG: Establishing SQLite database connection ```
Instance 2 ``` Log in instance 1 [2023-01-26 10:56:30] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:56:30] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:56:30] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:56:30] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 10:56:30] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:56:30] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:56:30] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:56:30] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:56:30] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:56:30] selfoss.DEBUG: Establishing SQLite database connection Log out of instance 2 [2023-01-26 10:57:48] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:57:48] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:57:48] selfoss.DEBUG: logged out and destroyed session Log in instance 2 [2023-01-26 10:59:22] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:59:22] selfoss.DEBUG: session does not contain valid auth [2023-01-26 10:59:22] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 10:59:22] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 10:59:22] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 10:59:22] selfoss.DEBUG: logged in using valid session [2023-01-26 10:59:22] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 10:59:22] selfoss.DEBUG: Establishing SQLite database connection Clear cookies and log in instance 1 [2023-01-26 11:02:57] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:02:57] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:02:57] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:02:57] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 11:02:57] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:02:57] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:02:57] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:02:57] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:02:57] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:02:57] selfoss.DEBUG: Establishing SQLite database connection Log out of instance 1 [2023-01-26 11:03:38] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:03:38] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:03:38] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:03:38] selfoss.DEBUG: Establishing SQLite database connection [2023-01-26 11:03:38] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:03:38] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:03:38] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:03:38] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:03:38] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:03:38] selfoss.DEBUG: Establishing SQLite database connection Log in instance 2 [2023-01-26 11:04:26] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:04:26] selfoss.DEBUG: session does not contain valid auth [2023-01-26 11:04:26] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 11:04:26] selfoss.DEBUG: logged in with supplied username and password [2023-01-26 11:04:26] selfoss.DEBUG: set cookie on localhost/selfoss_test/ expiring in 2592000 seconds [2023-01-26 11:04:26] selfoss.DEBUG: logged in using valid session [2023-01-26 11:04:26] selfoss.DEBUG: Creating database connection {"dsn":"sqlite:/home/ylxnfqev/domains/localhost/public_html/selfoss_test/src/helpers/../../data/sqlite/selfoss.db"} [2023-01-26 11:04:26] selfoss.DEBUG: Establishing SQLite database connection ```
davidoskky commented 1 year ago

Instance 2 has publicMode set to 1 if that could be relevant, didn't think about it earlier.

jtojnar commented 1 year ago

Oh, that explains it then.

The authentication works fine on server-side but the JavaScript client remembers whether it is signed in (and stores it in localstorage, which probably is not segregated by path).

If you try to access non-public mode instance, the client will get 403 from the server and go to login screen. If you try to access public instance while the client still remembers being logged in, it will be none the wiser.

jtojnar commented 1 year ago

I tried setting the scope to ./ in the web manifest but it does not seem to affect the Origin for the purpose of localStorage. Will need to come up with something else.