Summary
Session Fixation vulnerability in the CLI login flow in nerves-hub nerveshubweb allows an unauthenticated attacker to obtain an API token for another user's account via a crafted login link. Starting a CLI login with POST /api/auth/clisession needs no authentication and returns a polling token, a confirmation URL that carries that token, and a confirmation code. When a signed-in user opens that URL and clicks Confirm, NervesHub.Accounts.verifyclisessiontoken/2 creates an API token for the user's account and stores it on the login, and the next poll of GET /api/auth/clisession/<token> returns it to whoever started the login.
The confirmation code is only displayed and is never compared with anything, so it cannot show that the person confirming is the one who started the login. The confirm form carries a CSRF token and the page cannot be framed, so the attacker has to persuade the user to open the link and click the button themselves.
This issue affects nerveshub: from 2.5.0 before 2.5.3.
Details
1. Starting a login. nh user login, like any client of this flow, calls POST /api/auth/clisession, which needs no authentication. NervesHubWeb.API.UserController.clisession/2 calls NervesHub.Accounts.generateclisessiontoken/1, which stores a waiting login in the CLI session cache under a random UUID token with a six-digit confirmation code, and responds with the token, the code, and the URL /auth/cli/<token>.
2. Approving a login. GET /auth/cli/<token> requires a signed-in web user. NervesHubWeb.SessionController.cli/2 finds the login by the token from the URL, shows the code, and renders a form that posts back to /auth/cli/<token>. The form carries no code field. cliconfirm/2 passes the signed-in user and the token to NervesHub.Accounts.verifyclisessiontoken/2, which creates an API token for that user with createuserapitoken/2 and stores it on the login. Nothing compares the confirmation code with anything.
3. Collecting the token. GET /api/auth/clisession/<token>, also unauthenticated, returns the stored API token once the login is confirmed. Whoever started the login holds the token from step 1 and can poll until it arrives. The token is an ordinary API token and stays valid until the user deletes it.
Proof of concept
1. With no account, run curl -X POST https://<host>/api/auth/clisession. Note token, url and confirmationcode from the response. 2. Send url to someone with a NervesHub account, with a message such as "Please verify your NervesHub CLI access. Your code is <confirmationcode>." 3. They open it while signed in, see the code they were told to expect, and click "Confirm login". 4. curl https://<host>/api/auth/clisession/<token> returns "status": "ready" and a usertoken. 5. Send API requests with Authorization: token <usertoken>. They run as the person who confirmed.
Impact
An attacker with no account obtains an API token for any NervesHub user they can persuade to open a link and click Confirm. The token acts as that user through the API in every organization they belong to, at their role, until the user deletes it on the account page. Signing out of the web does not revoke it.
Workarounds
Block POST /api/auth/clisession at the reverse proxy until the upgrade. It is the only entry point that creates a CLI login, so no link can be produced while it is blocked. CLIs can still sign in with an email and password (nh user auth, POST /api/users/auth), or use an API token created on the account page.
Solutions
Upgrading does not revoke tokens already handed out. A token from a CLI login is an ordinary API token with a note the client chose, so one an attacker obtained looks like any other. After upgrading, users should review their API tokens on the account page and delete any they do not recognise.
Summary
Improperly Controlled Modification of Dynamically-Determined Object Attributes vulnerability in the device API, device forms, signing key and product forms and JITP settings in nerves-hub nerveshubweb allows an authenticated user who manages devices in any organization to write into other organizations via submitted orgid, productid and deploymentid fields. The device API create and update actions and the dashboard device forms pass the request parameters to NervesHub.Devices.Device.changeset/2, which casts the organization, product, deployment group and update state as given. The signing key and product forms merge the session's organization into the submitted parameters so that a submitted orgid wins, and the JITP changeset accepts any productid. Each request requires the manage role only in the user's own organization, and any account can create one.
A device placed on another organization's deployment group, or moved into its product, is sent that organization's firmware with a download URL. The user cannot change or control devices that already belong to the other organization, and cannot upload firmware to it.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Details
1. Device API and device forms. NervesHubWeb.API.DeviceController.create/2 sets orgid and productid from the route, then hands the rest of the request to Device.changeset/2; update/2 hands the whole request over. The changeset casts orgid, productid, deploymentid, deletedat and the server-managed update state, so an update can move the device into another organization's product and either request can place it on another organization's deployment group. The device settings form in NervesHubWeb.Components.DevicePage.SettingsTab and the new device form in NervesHubWeb.Live.Devices.New reach the same changeset with the same effect.
2. Signing key and product forms. NervesHubWeb.Live.Org.SigningKeys and NervesHubWeb.Live.Products.New build their parameters with Enum.into(submitted, %{"orgid" => sessionorgid}), so a submitted orgid overrides the session's, and the key or product is created in the organization named by the client.
3. JITP settings. NervesHub.Devices.CACertificate.JITP.changeset/2 casts any productid, through the API and the dashboard, so devices the certificate authority provisions are created in another organization's product.
4. Firmware delivery. When a planted device connects, NervesHub.ManagedDeployments checks its deployment group membership by firmware version, platform and architecture only, all reported by the device, so it stays on the foreign group and is sent that group's current release with a download URL.
Proof of concept
As an admin of organization A, with organization B having an active deployment group whose current release is firmware B:
1. POST /api/orgs/<A>/products/<A's product>/devices with {"identifier": "planted", "deploymentid": <B's deployment group ID>}. The device is created in A, on B's deployment group. 2. Create a device key for it, then connect it, reporting the platform and architecture of firmware B. When the deployment runs, the device is sent an update for firmware B with its download URL. 3. To move a device instead, PUT /api/orgs/<A>/products/<A's product>/devices/<identifier> with {"orgid": <B's ID>, "productid": <B's product ID>}. The response is 201, and the device is now in B's product.
Impact
Any user who manages devices in an organization of their own can attach their device to another organization's deployment group and receive its firmware, move devices into that organization's product, add firmware signing keys and products to it, and have a certificate authority provision devices into its product. Devices that already belong to the other organization are not controlled, and no firmware can be uploaded to it.
Solutions
The fixed release's migration takes every device off a deployment group that belongs to a different product and logs each one. Upgrading undoes nothing else done this way. After upgrading, check the database for devices whose organization does not own their product, for signing keys in orgkeys whose createdbyid has never been a member of the key's organization, and for certificate authorities whose JITP product belongs to another organization, and remove what you do not recognize. A device moved wholly into another organization, and a product added to one, leave nothing that sets them apart, so review your organization's devices and products as well.
Summary
Improper Authentication vulnerability in Google sign-in and email confirmation in nerves-hub nerveshubweb allows an attacker who registers another person's email address to share that person's account once they sign in. NervesHub.Accounts.updateorcreateuserfromueberauth/1 signs a Google user in to any account carrying the same email that is not yet linked to a Google account, links it and marks the email confirmed, without the account's owner ever having proved they own the address. NervesHubWeb.SessionController.confirm/2 likewise signs in whoever follows a confirmation link. An attacker registers the address from the sign-up form, changes their own account's email to it, or registers it as an organization admin from an invite link, and keeps the password; when the address's owner signs in with Google or follows the confirmation link, they land in that account.
The Google path also creates accounts with registrations closed and never checks Google's emailverified claim, and the API's password sign-in in NervesHubWeb.API.UserController issues tokens to accounts whose email was never confirmed. The attacker gains only what the victim is granted afterwards, and nothing on accounts whose owners never use either path.
This issue affects nerveshub: from 2.3.0 before 2.5.3.
Proof of concept
With Google sign-in turned on and registrations open:
1. Register an account with victim@example.com and a password you choose. Do not confirm it. 2. The owner of victim@example.com signs in to NervesHub with Google for the first time. They are signed in to your account, and its email is now marked confirmed. 3. An organization invites victim@example.com and the victim accepts while signed in. 4. Sign in with victim@example.com and your password. You are a member of the organization at the role it gave the victim.
Without Google sign-in, as an admin of an organization:
1. Invite victim@example.com, copy the invite link from the members page, and register from it with a password you choose. 2. Try to sign in with victim@example.com and your password. NervesHub refuses, since the email is not confirmed, and emails victim@example.com a confirmation link. 3. The victim follows the link and is signed in to your account. Keep using your session or sign in with your password.
Impact
An attacker who registers someone else's email address before that person first signs in with Google, or before they follow a confirmation link, ends up sharing that person's account: the attacker keeps signing in with the password they chose and sees and does whatever the victim can, in every organization the victim joins, at the victim's role. On an account linked to Google the victim cannot reset the password to lock the attacker out.
Workarounds
Turn off Google sign-in by unsetting GOOGLECLIENTID until the upgrade; users who only sign in with Google cannot sign in while it is off. This does not close the confirmation link path. Turning off registrations stops strangers using the sign-up form, but not an organization admin registering from an invite link.
Solutions
Upgrading does not undo links already made. Review the users rows that carry both a passwordhash and a googleid; most are one person signing in both ways, but an account registered for someone else's address was usually created well before its first Google sign-in, so compare insertedat with googlelastsyncedat. For one its owner did not set up, set its googleid to NULL, delete its usertokens rows to end its sessions and revoke its API tokens, and have the address's owner reset the password. An account taken through a confirmation link looks the same as one its owner set up; its owner can end anyone else's access by resetting the password, which ends every session and revokes every API token. Before upgrading, check how your instance lets people sign up: SIGNUPMETHODS replaces OPENFORREGISTRATIONS, and instances that relied on Google sign-in to create accounts while registrations were off need SIGNUPMETHODS=google.
Summary
Improper Authentication vulnerability in Google sign-in and email confirmation in nerves-hub nerveshubweb allows an attacker who registers another person's email address to share that person's account once they sign in. NervesHub.Accounts.updateorcreateuserfromueberauth/1 signs a Google user in to any account carrying the same email that is not yet linked to a Google account, links it and marks the email confirmed, without the account's owner ever having proved they own the address. NervesHubWeb.SessionController.confirm/2 likewise signs in whoever follows a confirmation link. An attacker registers the address from the sign-up form, changes their own account's email to it, or registers it as an organization admin from an invite link, and keeps the password; when the address's owner signs in with Google or follows the confirmation link, they land in that account.
The Google path also creates accounts with registrations closed and never checks Google's emailverified claim, and the API's password sign-in in NervesHubWeb.API.UserController issues tokens to accounts whose email was never confirmed. The attacker gains only what the victim is granted afterwards, and nothing on accounts whose owners never use either path.
This issue affects nerveshub: from 2.3.0 before 2.5.3.
Proof of concept
With Google sign-in turned on and registrations open:
1. Register an account with victim@example.com and a password you choose. Do not confirm it. 2. The owner of victim@example.com signs in to NervesHub with Google for the first time. They are signed in to your account, and its email is now marked confirmed. 3. An organization invites victim@example.com and the victim accepts while signed in. 4. Sign in with victim@example.com and your password. You are a member of the organization at the role it gave the victim.
Without Google sign-in, as an admin of an organization:
1. Invite victim@example.com, copy the invite link from the members page, and register from it with a password you choose. 2. Try to sign in with victim@example.com and your password. NervesHub refuses, since the email is not confirmed, and emails victim@example.com a confirmation link. 3. The victim follows the link and is signed in to your account. Keep using your session or sign in with your password.
Impact
An attacker who registers someone else's email address before that person first signs in with Google, or before they follow a confirmation link, ends up sharing that person's account: the attacker keeps signing in with the password they chose and sees and does whatever the victim can, in every organization the victim joins, at the victim's role. On an account linked to Google the victim cannot reset the password to lock the attacker out.
Workarounds
Turn off Google sign-in by unsetting GOOGLECLIENTID until the upgrade; users who only sign in with Google cannot sign in while it is off. This does not close the confirmation link path. Turning off registrations stops strangers using the sign-up form, but not an organization admin registering from an invite link.
Solutions
Upgrading does not undo links already made. Review the users rows that carry both a passwordhash and a googleid; most are one person signing in both ways, but an account registered for someone else's address was usually created well before its first Google sign-in, so compare insertedat with googlelastsyncedat. For one its owner did not set up, set its googleid to NULL, delete its usertokens rows to end its sessions and revoke its API tokens, and have the address's owner reset the password. An account taken through a confirmation link looks the same as one its owner set up; its owner can end anyone else's access by resetting the password, which ends every session and revokes every API token. Before upgrading, check how your instance lets people sign up: SIGNUPMETHODS replaces OPENFORREGISTRATIONS, and instances that relied on Google sign-in to create accounts while registrations were off need SIGNUPMETHODS=google.
Summary
Incorrect Authorization vulnerability in the devices page bulk move in nerves-hub nerveshubweb allows an authenticated user with the manage role in one organization and only the view role in another to move devices into the second organization's product via the "Move device(s) to product" action. The target-product event in NervesHubWeb.Live.Devices.Index looks the product up with NervesHub.Products.getbyid/2, which checks that the user is a member of the product's organization at any role, and move-devices-product then changes each selected device's organization and product. The device API's move requires manage in the target organization, and an earlier fix added the check on the organization the devices leave but not on the one they enter.
A moved device keeps its key and certificate, joins the target organization's matching deployment groups, and is sent their firmware with a download URL, which the view role cannot otherwise obtain. The user cannot change or control devices that already belong to the other organization.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Details
1. Target selection. The bulk actions sidebar (NervesHubWeb.Components.BulkActionsSidebar) lists the products of every organization in currentscope.user.orgs. Choosing one sends target-product to NervesHubWeb.Live.Devices.Index, which requires device:update in the current organization and then calls NervesHub.Products.getbyid/2. That query joins the product's organization to its orgusers rows and filters on the user's id only, so any membership in the target organization satisfies it, including the view role.
2. The move. move-devices-product passes the selected devices, or every device matching the current filter, to NervesHub.Devices.BulkActions.movemany/3, which calls Devices.move/3 for each one and rewrites its orgid and productid. No check of the user's role in the target organization happens on this path, while the API's move in NervesHubWeb.API.DeviceController requires manage there.
3. Effect. The moved device still authenticates with its own certificate. On its next connection it is matched against the target product's deployment groups by platform, architecture and tags, joins one, and is sent that group's firmware with a download URL.
Proof of concept
As a user with manage in organization A and view in organization B, where B has an active deployment group:
1. On A's devices page, give a device you control the tags B's deployment group asks for. A view member can see the group's conditions. 2. Select the device, choose B's product under "Move device(s) to product" and press Move. The page reports the move as successful, and the device is now in B's product. 3. Connect the device, reporting the platform and architecture of the group's firmware. It joins the group and is sent B's firmware with a download URL.
Impact
A user who manages devices in one organization and holds only the view role in another can move their own devices into the second organization. The devices join its matching deployment groups and receive its firmware, which the view role cannot otherwise download, and they report health, logs and alarms into that organization. Devices already belonging to the other organization are not affected.
Solutions
Every move is recorded in the target product's audit log as "User <name> moved device <identifier> to <org> : <product>". After upgrading, review the auditlogs rows with resource type NervesHub.Products.Product and a description containing "moved device" whose actor does not hold the manage or admin role in that organization, and move or remove the devices they brought in. Roles may have changed since a move, and entries older than the retention period are gone when TRUNCATEAUDITLOGSENABLED is on.
Summary
Incorrect Authorization vulnerability in the devices page bulk move in nerves-hub nerveshubweb allows an authenticated user with the manage role in one organization and only the view role in another to move devices into the second organization's product via the "Move device(s) to product" action. The target-product event in NervesHubWeb.Live.Devices.Index looks the product up with NervesHub.Products.getbyid/2, which checks that the user is a member of the product's organization at any role, and move-devices-product then changes each selected device's organization and product. The device API's move requires manage in the target organization, and an earlier fix added the check on the organization the devices leave but not on the one they enter.
A moved device keeps its key and certificate, joins the target organization's matching deployment groups, and is sent their firmware with a download URL, which the view role cannot otherwise obtain. The user cannot change or control devices that already belong to the other organization.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Details
1. Target selection. The bulk actions sidebar (NervesHubWeb.Components.BulkActionsSidebar) lists the products of every organization in currentscope.user.orgs. Choosing one sends target-product to NervesHubWeb.Live.Devices.Index, which requires device:update in the current organization and then calls NervesHub.Products.getbyid/2. That query joins the product's organization to its orgusers rows and filters on the user's id only, so any membership in the target organization satisfies it, including the view role.
2. The move. move-devices-product passes the selected devices, or every device matching the current filter, to NervesHub.Devices.BulkActions.movemany/3, which calls Devices.move/3 for each one and rewrites its orgid and productid. No check of the user's role in the target organization happens on this path, while the API's move in NervesHubWeb.API.DeviceController requires manage there.
3. Effect. The moved device still authenticates with its own certificate. On its next connection it is matched against the target product's deployment groups by platform, architecture and tags, joins one, and is sent that group's firmware with a download URL.
Proof of concept
As a user with manage in organization A and view in organization B, where B has an active deployment group:
1. On A's devices page, give a device you control the tags B's deployment group asks for. A view member can see the group's conditions. 2. Select the device, choose B's product under "Move device(s) to product" and press Move. The page reports the move as successful, and the device is now in B's product. 3. Connect the device, reporting the platform and architecture of the group's firmware. It joins the group and is sent B's firmware with a download URL.
Impact
A user who manages devices in one organization and holds only the view role in another can move their own devices into the second organization. The devices join its matching deployment groups and receive its firmware, which the view role cannot otherwise download, and they report health, logs and alarms into that organization. Devices already belonging to the other organization are not affected.
Solutions
Every move is recorded in the target product's audit log as "User <name> moved device <identifier> to <org> : <product>". After upgrading, review the auditlogs rows with resource type NervesHub.Products.Product and a description containing "moved device" whose actor does not hold the manage or admin role in that organization, and move or remove the devices they brought in. Roles may have changed since a move, and entries older than the retention period are gone when TRUNCATEAUDITLOGSENABLED is on.
Summary
Incorrect Authorization vulnerability in the devices page bulk move in nerves-hub nerveshubweb allows an authenticated user with the manage role in one organization and only the view role in another to move devices into the second organization's product via the "Move device(s) to product" action. The target-product event in NervesHubWeb.Live.Devices.Index looks the product up with NervesHub.Products.getbyid/2, which checks that the user is a member of the product's organization at any role, and move-devices-product then changes each selected device's organization and product. The device API's move requires manage in the target organization, and an earlier fix added the check on the organization the devices leave but not on the one they enter.
A moved device keeps its key and certificate, joins the target organization's matching deployment groups, and is sent their firmware with a download URL, which the view role cannot otherwise obtain. The user cannot change or control devices that already belong to the other organization.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Details
1. Target selection. The bulk actions sidebar (NervesHubWeb.Components.BulkActionsSidebar) lists the products of every organization in currentscope.user.orgs. Choosing one sends target-product to NervesHubWeb.Live.Devices.Index, which requires device:update in the current organization and then calls NervesHub.Products.getbyid/2. That query joins the product's organization to its orgusers rows and filters on the user's id only, so any membership in the target organization satisfies it, including the view role.
2. The move. move-devices-product passes the selected devices, or every device matching the current filter, to NervesHub.Devices.BulkActions.movemany/3, which calls Devices.move/3 for each one and rewrites its orgid and productid. No check of the user's role in the target organization happens on this path, while the API's move in NervesHubWeb.API.DeviceController requires manage there.
3. Effect. The moved device still authenticates with its own certificate. On its next connection it is matched against the target product's deployment groups by platform, architecture and tags, joins one, and is sent that group's firmware with a download URL.
Proof of concept
As a user with manage in organization A and view in organization B, where B has an active deployment group:
1. On A's devices page, give a device you control the tags B's deployment group asks for. A view member can see the group's conditions. 2. Select the device, choose B's product under "Move device(s) to product" and press Move. The page reports the move as successful, and the device is now in B's product. 3. Connect the device, reporting the platform and architecture of the group's firmware. It joins the group and is sent B's firmware with a download URL.
Impact
A user who manages devices in one organization and holds only the view role in another can move their own devices into the second organization. The devices join its matching deployment groups and receive its firmware, which the view role cannot otherwise download, and they report health, logs and alarms into that organization. Devices already belonging to the other organization are not affected.
Solutions
Every move is recorded in the target product's audit log as "User <name> moved device <identifier> to <org> : <product>". After upgrading, review the auditlogs rows with resource type NervesHub.Products.Product and a description containing "moved device" whose actor does not hold the manage or admin role in that organization, and move or remove the devices they brought in. Roles may have changed since a move, and entries older than the retention period are gone when TRUNCATEAUDITLOGSENABLED is on.
Summary
Missing Authorization vulnerability in the device and deployment group pages in nerves-hub nerveshubweb allows an authenticated organization member with the view role to change devices and deployment groups via LiveView events reserved for the manage role. The event handlers that add and delete device certificates, add and remove tags, overwrite or clear a device's manual location, remove a device from its deployment group, move matched devices into a deployment group or remove unmatched ones, import devices from a CSV, and start, retry or delete firmware delta builds carry out the change without calling authorized!/2, and the pages render the controls to every member.
A view member can add a certificate that lets whoever holds its key connect as the device, delete a certificate so the device can no longer authenticate with it, and change which deployment group, and so which firmware release, a device receives. Everything stays within the organizations the member belongs to.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Details
The dashboard reads the member's role into currentscope when a page mounts, and each privileged event handler is expected to call authorized!/2 with the permission it needs, all of which resolve to the manage role in lib/nerveshubweb/helpers/authorization.ex. These handlers never do:
Device settings tab (NervesHubWeb.Components.DevicePage.SettingsTab): hookedevent/3 for delete-certificate, and handleprogress/3 for the certificate upload, which should require device:update.
Device details tab (NervesHubWeb.Components.DevicePage.DetailsTab): hookedevent/3 for add-tag, remove-tag, save-location-changes and clear-manual-location-information (device:update), and remove-from-deployment-group (device:set-deployment-group).
Deployment group page (NervesHubWeb.Live.DeploymentGroups.Show and NervesHubWeb.Components.DeploymentGroupPage.Summary): handleevent/3 for move-matched-devices-to-deployment-group and remove-unmatched-devices-from-deployment-group, and handleprogress/3 for the devicecsv upload (device:set-deployment-group), plus generate-firmware-deltas, retrydelta and deletedelta (deploymentgroup:update).
The pages show every one of these controls to view members, so each change takes a click, and a client can send the events directly over the LiveView socket regardless.
Proof of concept
1. Create deployment group canary with conditions matching tag beta. 2. Create deviceoutsidematch in the same product with tag beta and no deployment group, and deviceinsidemismatch in deployment group canary with tag foo. 3. Sign in as a member of the organization with the view role and open /org/<org>/<product>/deploymentgroups/canary. 4. Click Move device(s): deviceoutsidematch is now in canary. Click Remove device(s): deviceinsidemismatch no longer has a deployment group. 5. As the same member, open a device in the product and add a tag. The tag is saved. 6. On the device's settings tab, delete a certificate, or upload a self-signed one. The change is saved, and a client presenting the uploaded certificate connects as the device.
Impact
An organization member with the view role can add or delete a device's certificates, change its tags and location, and move devices into or out of deployment groups, which changes the firmware release they receive. An added certificate lets whoever holds its key connect as the device and persists after the member leaves. Everything stays within the organizations the member belongs to.
Workarounds
No configuration closes the hole. Until the upgrade, give the view role only to people you would trust with the manage role on that organization's devices.
Solutions
Upgrading does not remove a certificate that a view member already added. After upgrading, review each device's certificates and delete any you do not recognize.
Summary
Improper Session Invalidation vulnerability in the dashboard pages, device console and local shell channels in nerves-hub nerveshubweb allows an organization member who is removed or given a lower role to keep acting at their old role through anything they had open at the time. The dashboard reads the member's role once when a page mounts, in the assignorgtoscope hook of NervesHubWeb.Auth, and the console, local shell and device event stream channels check membership once at join. Removing a member or changing their role tells none of them, so open pages keep carrying out actions and open consoles keep running commands on the device until the page reloads or the socket disconnects.
The dashboard also opens consoles over NervesHubWeb.UserSocket with a token that holds only the user's id, is accepted for 24 hours, and is not revoked by signing out, which disconnects only the session's LiveViews. Whoever holds a token taken from a page can open consoles as that user, within the user's current membership, until it expires.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Proof of concept
1. In an organization, A is an admin and B has the manage role. B opens a device's page and its Console tab. 2. A removes B from the organization on the organization's Users page, or lowers B's role to view. 3. Without reloading, B's open page still carries out actions and B's console still accepts input, until B reloads the page or the socket disconnects. 4. For the socket token: while signed in, copy the data-user-token attribute of the #console element, sign out, and within 24 hours connect a Phoenix socket client to /socket/websocket with that token. Joining user:console:identifier-<device identifier> succeeds.
Impact
A member who is removed from an organization or given a lower role keeps their old access through whatever they had open at the time, including device consoles and local shells that run commands on the device, until the page reloads or the socket disconnects. Anyone holding the dashboard's socket token taken from a page can open consoles as that user, within that user's current permissions, for up to 24 hours after they sign out.
Workarounds
After removing a member or lowering their role, restart the web nodes. That closes every open page and console, and each one is checked again when it reconnects. A socket token cannot be revoked before it expires short of changing SECRETKEYBASE, which signs everyone out.
Summary
Improper Session Invalidation vulnerability in the dashboard pages, device console and local shell channels in nerves-hub nerveshubweb allows an organization member who is removed or given a lower role to keep acting at their old role through anything they had open at the time. The dashboard reads the member's role once when a page mounts, in the assignorgtoscope hook of NervesHubWeb.Auth, and the console, local shell and device event stream channels check membership once at join. Removing a member or changing their role tells none of them, so open pages keep carrying out actions and open consoles keep running commands on the device until the page reloads or the socket disconnects.
The dashboard also opens consoles over NervesHubWeb.UserSocket with a token that holds only the user's id, is accepted for 24 hours, and is not revoked by signing out, which disconnects only the session's LiveViews. Whoever holds a token taken from a page can open consoles as that user, within the user's current membership, until it expires.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Proof of concept
1. In an organization, A is an admin and B has the manage role. B opens a device's page and its Console tab. 2. A removes B from the organization on the organization's Users page, or lowers B's role to view. 3. Without reloading, B's open page still carries out actions and B's console still accepts input, until B reloads the page or the socket disconnects. 4. For the socket token: while signed in, copy the data-user-token attribute of the #console element, sign out, and within 24 hours connect a Phoenix socket client to /socket/websocket with that token. Joining user:console:identifier-<device identifier> succeeds.
Impact
A member who is removed from an organization or given a lower role keeps their old access through whatever they had open at the time, including device consoles and local shells that run commands on the device, until the page reloads or the socket disconnects. Anyone holding the dashboard's socket token taken from a page can open consoles as that user, within that user's current permissions, for up to 24 hours after they sign out.
Workarounds
After removing a member or lowering their role, restart the web nodes. That closes every open page and console, and each one is checked again when it reconnects. A socket token cannot be revoked before it expires short of changing SECRETKEYBASE, which signs everyone out.
Summary
Improper Session Invalidation vulnerability in the dashboard pages, device console and local shell channels in nerves-hub nerveshubweb allows an organization member who is removed or given a lower role to keep acting at their old role through anything they had open at the time. The dashboard reads the member's role once when a page mounts, in the assignorgtoscope hook of NervesHubWeb.Auth, and the console, local shell and device event stream channels check membership once at join. Removing a member or changing their role tells none of them, so open pages keep carrying out actions and open consoles keep running commands on the device until the page reloads or the socket disconnects.
The dashboard also opens consoles over NervesHubWeb.UserSocket with a token that holds only the user's id, is accepted for 24 hours, and is not revoked by signing out, which disconnects only the session's LiveViews. Whoever holds a token taken from a page can open consoles as that user, within the user's current membership, until it expires.
This issue affects nerveshub: from 1.0.0 before 2.5.3.
Proof of concept
1. In an organization, A is an admin and B has the manage role. B opens a device's page and its Console tab. 2. A removes B from the organization on the organization's Users page, or lowers B's role to view. 3. Without reloading, B's open page still carries out actions and B's console still accepts input, until B reloads the page or the socket disconnects. 4. For the socket token: while signed in, copy the data-user-token attribute of the #console element, sign out, and within 24 hours connect a Phoenix socket client to /socket/websocket with that token. Joining user:console:identifier-<device identifier> succeeds.
Impact
A member who is removed from an organization or given a lower role keeps their old access through whatever they had open at the time, including device consoles and local shells that run commands on the device, until the page reloads or the socket disconnects. Anyone holding the dashboard's socket token taken from a page can open consoles as that user, within that user's current permissions, for up to 24 hours after they sign out.
Workarounds
After removing a member or lowering their role, restart the web nodes. That closes every open page and console, and each one is checked again when it reconnects. A socket token cannot be revoked before it expires short of changing SECRETKEYBASE, which signs everyone out.