Stolen session token (possible in nextcloud)

Without wanting to evaluate any of the suggestions here, I would like to remind that an admin can deactivate a user account if there is suspicion of misuse/takeover of the account. I have already used this in emergencies and everything is first “frozen”:

./occ user:disable <uid>

This does not delete the user, but basically does what the OP is looking for. If everything is clarified on side channels, the password can be reset via occ and the account can be reactivated.

this is an interesting one, gonna test it
realy excited to see if the session is gonna freeze up and not be able to use

to get the user ID i use this

userID & username

sudo -u www-data php occ user:list --limit=1000 --output=json_pretty

all user information

sudo -u www-data php occ user:list --limit=1000 --info --output=json_pretty

more here github link

there was no suggestion on the one hand side as of today i dont know why config.php is loosing config entries and on the other hand side there was till your information no way of kickin a user with a stolen session token out to force the user to reauth and get a new session token

if the way with disabling the user kills the session
this will be scriptable and part of the written emergency plan.
better to kick them all out cuz at 3 in the mornin you don’t know jack!

but is this a doable sollution … ?
a mid size NC 50 - 60 users ??

gonna look into this
br so long NP

This is how one itterate through all existing users, even if those users have uid containing spaces (makes use of jq sudo apt-get instll jq):

#!/bin/bash
# change webserver user and path accordingly:
occ_call="sudo -u www-data php -f /var/www/nextcloud/occ"
tolower(){ echo "$*"|tr [:upper:] [:lower:]; }

# We need to take the detour via base64 to allow usernames with spaces
for user in $(echo $($occ_call user:list --output=json | jq -r 'keys_unsorted[] | @base64')); do
    user="$(echo "$user" | base64 --decode)"
    echo "processing User $user"
    echo
    read -p "Do you want to disable the account of user \"$user\" (^C to finish loop) (y/N)? " choice
    if [ "$(tolower ${choice:-n})" = "y" ]; then
        echo "Disabling useraccount of user  \"$user\""
        occ_call user:disable "$user"
    else
        echo "User  \"$user\" not disabled."
    fi
    echo
done

This is a shot from the hip without testing it, you should of course first test it with this line commented out as here::

#        occ_call user:disable "$user"
2 Likes

Pragmatic and simple. Works for what is requested. The conceptual discussion of what Nextcloud should cake in and not, is unrelated. I suggest @ernolf is marked as solution to the “letter of law” of the question. This discussion has turned into a principal discussion, and I do find it relevant, but I suggests that part of it is split to a new thread?

1 Like

There are actually three questions / issues in the original post of @n0plan:

  1. Is steeling a session and log in with it on another browser / computer possible with Nextcloud? (as shown in the video)

    Simple answer: Yes, it is.

  2. The config.php loses the additional configuration parameters, which should mitigate the risk that someone can use a stolen session token. For this issue OP already created a separate thread: Forum Link: Config.php loosing entries

    Not sure why this is happening, but but if someone has any ideas that might help with this, this person can reply in the other thread.

  3. A feature to kick / logoff all users

    Has been answerd by @ernolf

4 Likes

hi, but this is not solving the issue, we are adressing in the 1st place (get access to the system with a stolen session token)

I’ve tested the way diabling users, yes works fine as expected.
2things to mention if you run it

  1. you’ll disable ALL users and ALL their connected devices
  2. the stolen session token is still active and valid

ad 2) you have to shut all your users down / out of NC (disable them) until your

login_cookie ( Defaults to 60*60*24*15 seconds (15 days) )
session_lifetime ( Defaults to 60*60*24 seconds (24 hours) )

runs out … means you have to wait at least 24 hours or in some cases longer but lets play with the defaults.

Where I come from 24 hours BUSINESS STANDS STILL is kind of mission critical and will get your ass pretty fast escorted out of the building.

yes we have kicked them (the bad ones) out (with all the others)

next step we have to compare and check log-files and get a list,which user is connected with what kind of device (webIf / windows client / mobile device / and on and on) then you have to run these IPs grouped by user through some GEO-IP filter/information to check if eg your German users are conneced from German IPs (yes i know there are VPNs and no one would be stupid to attack without hiding at least the origion of his public IP) and not via IPs from another part of the world (cross check against your firewall / vpn gateway to rule out your legit users, who are gonna call you right away when you kicked em out of service while on a meeting in Los Angeles)

what you got so far is a rough validated list of
user IDs | IP Adress | Geo Info

next step sort all the inactive people out of the list, (you have to do some calculation if their session is expired or not but get it simple this time)

then you get a list

user IDs | IP Adress | Geo Info | active within $session_lifetime - now |

active now will not do the trick cuz this session token could be stolen / compromised too !

with this information you can now start to disbale the user and keep them out until the $session_lifetime is expired.

BECAUSE there is at the moment as far as i see
NO WAY to revoke the session token and forece the user (that means you know exact which user) to reauth with their credentials.

I hope you now got a better understandig @Kerasit why this is not solved.

Kill / revoke all session tokens at once would be an interesting thing to test.
but again kill all session tokens or only the active ones …
so there is more into that because this is a pretty awesome product and all over the world more and more people store personal and protectabel information with this product, so we the community have to help em out when shit hits the fan, in a way thats also doable for the non IT professional.

br NP

I haven’t been reading this entire thread, but surely you can just delete whichever session you want from the session store, to get rid of it immediately? If PHP can’t find a given session key on its end, the session is moot, it no longer exists. I don’t see why you have to wait.

:rofl: :rofl:

i have not found this way yet … any hints ?

im testing right now again what disabling and enabling a user will do within an existing session
last test the session-token was still valid and the user was not forced to reauth

reauth (thats the goal of the mission here)

keep you posted

Well the sessions are stored/tracked using files in the filesystem or in a database, or by other means, depending on what the PHP application is written to do. See PHP: Introduction - Manual and https://www.php.net/manual/en/session.customhandler.php for more information. Either way, if a session’s state is deleted on the server, then naturally that session no longer exists.

yeep sounds legit !

test results now i’ve tested on my own :wink:

step 1

log in with user incl 2FA

step 2 (disable the user)

sudo -u www-data php occ user:disable c911a911-6523-103a-999c-7aabaa7g41X0

result
user sesion freeze klickin around default screen shows up

user deactivated

if you are to fast with

sudo -u www-data php occ user:enable c911a911-6523-103a-999c-7aabaa7g41X0

it seems that the session token does not change on the browser
but without the 2FA (eg yubikey) you are not able to login (interesting)

you wait a little longer …
session token changed

next step to test it with a user that has some devices via TOKEN attached
if something nasty shows up (like entering the token for the device again, cuz this woukd be a showstopper for enabling / disabling a user … would be the last but in the moment the only line of defense)

oh this is somehow not funny resulting of watching a youtube video :wink:

NP

The sessions cookies are stored in the table oc_authtoken

I could immediately log out any client, and in special the cookies could I revoke (delete), which results in an instant logout/login-screen and nothing else.

It would be not much of an effort to create a “Panic Button” like script, that revokes ALL existing and active session cookies, without disconnecting any other (trusted) clients.

I am at the hospital and only with a little laptop. I will return here, as soon as I have something that could be published, if somebody would appreciate it.

But you can just do it directly in the sql console:

DELETE FROM oc_authtoken
WHERE remember = '1';

Thats all.

hospital get well soon or best wishes to the ones u r visiting !

test
user-reggi added to talk-APP on iphone with token

startet active call with users
disabled user-reggi during the call

user-reggi lost connection within 5 seconds
as a matter of fact he was also not able to log in on the webIf either (as we all know;)

the account on the iphone talk-app was gone

after enabling user-reggi again

i typed in the original token for the talk iphone-app
and guess what … it worked (can I say that i reused / recycled the token)

if it is possible to steal the token from an app even if it is possible this will bring you some other bigger problems after enabling the user again

(cuz deaktivating a user seems to kill the session token for the webIF)

the sollution we are talking about (disable / enable a user)
will get the stolen session token of the webInterface of NC solved (as far as we know of today)

BUT brings another issue/and problem for the admin and the user, all of the devices and apps per device (mobile / tab / chromebook / android / iOs whatever) you have added to the user via token (the only way after enabling 2FA) have to be set up again because the informations are gone (after disable / enable a user) as a matter of fact u can reuse the original token (as we tested here a couple of minutes ago) to set up the account for the app again. (if you stored the QR code in your documentation too it will not be that pain in the ass typing that token on a mobile device)

BUT is that the way to do it ? reuse a token after you executed a part of an emergency procedure ?

Therefore I was talking all the way down this post … active user / session / where they come from / active now / last within the session_lifetime / force to reauth …

to kick bad actors out of the system and force them to reauth with the credentials and 2FA

If we are going deep dive to do this on SQL console (killing sessions from the session store ) we should go and only kill webInterface sessions, and let all other sessions (eg talk-app on iPhone untouched) this will get us pretty close to a doable sollution (what di u think)

and hopefully someone will tell us that a token used to auth the app can not be stolen, and we can ignore that …

NP

But that is exactly what I did with

It only kicks loged in webInterface sessions and keeps everything else untouched.

Now one could make a wrapper around it, to live monitor who is actually logged in and one could exlude certain accounts but that’s the core of it.

1 Like

I just made this quick solution to see who is actually logged in on a web frontend and what session cookies are still “alive”

I named it nc-who (after the Unix who command):

/usr/local/bin/nc-who

#!/bin/bash
# enter your secrets here:
db_user=%DB_USER%
db_pass=%DB_PASS%
db_name=nextcloud
db_pref=oc_
#db_vertical="--auto-vertical-output"
db_vertical="--vertical"

db_strg="mysql -u $db_user -p$db_pass $db_vertical --disable-auto-rehash --default-character-set=utf8mb4 $db_name -e"
db_query="SELECT FROM_UNIXTIME(last_activity) AS last_activity, FROM_UNIXTIME(last_check) AS last_check, uid, name AS client FROM ${db_pref}authtoken WHERE type = '0' AND remember = '1' ORDER BY last_activity DESC, last_check DESC"

watch -tn 1 "$db_strg \"$db_query\""

create this file in your path (I recommend /usr/local/bin/nc-who)
Make it executable:

sudo chmod +x /usr/local/bin/nc-who

And now you can watch in a terminal, who is actually loged in. It refreshes once per second, it sorts by recent activity, newest (last activities) first.

This should be just a first step, the “monitoring” part.

2 Likes

Hello @ernolf you’re script could see loggued users with navigators, it’s very good, but how to see users who are connected with mobile (androis, ios) application ?

And after it’s possible to remove sessions for thoses users ?

Best regards

This script was intended to only show session-cookies that are still alive.
You can see all registred logins when you change the querry a little bit.
I have changed the script so that you can choose on startup if you only want to see the logins with session cookies or all registred logins.
When they are listed, does not mean, that those users are realy loged in. Therefore it is ordered by last activity.

Update it with this command:

[Edit]: … new home of the nc-who script is here:


you should do that in the mysql console yourself on your own risk.
If you are not that good in SQL-commandline, than you can do it in phpMyAdmin and delete the sessions you want to delete from there.

1 Like