-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kibana Security to use Server Side Sessions #17870
Comments
Original comment by @jaymode: Just to note for phase 2, I see some overlap with the idea of supporting sessions in security on the elasticsearch side (LINK REDACTED). The writeup there is probably a bit outdated in terms of how I think we'd do it now with the move to a full on HttpClient coming in the future. With that move I'd tend to think that we'd implement the a lightweight version of a |
Original comment by @lukasolson: @kjbekkelund and @alexbrasetvik Would like to hear your opinions on how this could potentially affect/integrate with Cloud. |
Original comment by @alexbrasetvik: Hi. Currently on vacation. Traveling home on Friday. Will comment properly then. We should not make any assumptions on which backend server gets which request, and we cannot turn on sticky sessions on the Cloud load balancers. |
Original comment by @kjbekkelund: It is definitely possible to implement secure alternatives that don't rely on state on the backend, e.g. LINK REDACTED. These tokens can either be saved in Web Storage (localstorage, sessionstorage) and sent in an |
Original comment by @skearns64: I'm +1 on further investigation of how we do this - server side sessions may not be the best way to solve the problem, but they do have some advantages. JWT is a good standard, but if I understand it correctly, our current model doesn't align with it; we're storing encrypted usernames and passwords in the cookie (and would need them in JWT), because we need to pass them both to ES for auth purposes. We could consider switching the Kibana model further, so that all requests are made by the Kibana Server user, and impersonates the end-user when appropriate. That way, we wouldn't need Kibana to ever store or pass passwords anywhere. |
UPDATE: updated #17870 (comment) with the current state of things and preliminary plan |
We could consider storing sessions in an alternate index, similar to how Elasticsearch stores its tokens in the
When you say "and keep in memory", are you thinking about a session cache on the Kibana server? |
Yep, that's an option for sure! The more I think about it, the more reasonable it feels.
Ugh, sorry, it's a left over from the original comment - I don't think we need to store anything in the server memory unless we really need to for the performance reasons - I'll update comment. |
Here are my initial thoughts:
I’m not sure we get any concrete benefit from encrypting the session ID. If anything, this may just pose additional risk, as it would allow an attacker to force Kibana to decrypt data (could allow algorithmic complexity attack to result in DoS). Since don’t need to allow users to set their own session IDs, we should generate them on the server side. The session ID should just be an opaque identifier, nothing more.
Just to clarify: I think we probably only want to encrypt sensitive data (such as credentials or PII), right? That way we can query on the other data.
I think this is the right approach. We are talking about storing user credentials with reversible encryption (in the case of
I think we should consider adding the following:
This would mean two cluster calls every time a user makes an HTTP request — one to fetch the session, another to update its last-access timestamp. I don’t think we need this in the session store, as this information will be available in the audit log (after it is overhauled)
As mentioned above, we’ll also need to capture roles.
(The statement above was incomplete in my original comment; edited to the following) Other thoughts:
|
I want to chew on this some more, but I agree with your assessment @jportner w/r/t not encrypting session identifiers, and including additional AAD so that a malicious actor can't perform a credential dump.
++
I want to challenge this requirement. Is this really something that folks need for compliance? If so then it's not enough that the list of roles have changed; It's possible that the privileges granted to one of the user's assigned roles was updated. Having just a list of roles would not be enough to detect that a user's privileges have in fact changed.
I think storing the IP address initially would be sufficient. We can always specify an GeoIP Ingest Pipeline to populate this for us if we ever want or need this capability. @legalastic I'm seeing mixed messages online -- is an IP address considered PII? We are considering storing and associating a user's IP address with their Kibana session, for auditing purposes, but also for potential features down the line (e.g., limiting number of sessions per IP, or invalidating sessions if the user's IP address has changed). This data lives within the user's cluster, and never leaves the user's cluster. It will also be periodically cleaned up as sessions are invalidated/expired, but the lifespan of this data is TBD and user-configurable to an extent.
Would this be something we update every time we see it change, or would the initial user agent be sufficient?
We could try to challenge this one as well, to reduce the impact of server-side sessions. If it turns out to be problematic, we could issue an update if the last seen access timestamp > 5 minutes ago (configurable), or something to that effect. |
The requirement is from NIST SP 800-53, AC-10 CONCURRENT SESSION CONTROL. See text excerpt
Organizations may define the maximum number of concurrent sessions for information system accounts globally, by account type (e.g., privileged user, non-privileged user, domain, specific application), by account, or a combination. For example, organizations may limit the number of concurrent sessions for system administrators or individuals working in particularly sensitive domains or mission-critical applications. This control addresses concurrent sessions for information system accounts and does not address concurrent sessions by single users via multiple system accounts. Since this control would be in place to prevent concurrent sessions by role to satisfy the "by account type" stipulation, we don't necessarily care if that role has been edited / underlying privileges have changed. We just care which users have that role.
Yeah, I was under the impression that it might be considered PII so that's why I suggested storing the geolocation, I should have mentioned that. I'm glad you called it out.
I see this as for informational purposes only, not to be used as any sort of security control. So I think we only need to store the initial user agent, as that's not something that would change in normal usage. |
Yep, that's what we already have.
Yes, I was just thinking that we may want to store part of the AAD in the cookie or some other info we don't want user to change, but if we end up with only session ID they we don't need to encrypt it, agree.
Correct.
++
You can have equal usernames in different realms, so the hash most likely should be based on username, provider type and provider name (or ES realm name, TBD) to cover "limit user's concurrent session" requirement.
That one is tricky indeed... In the absolute majority of the installations this won't be needed, so I think we can optimize here a bit with bulk requests depending on whether these controls are enabled or not for the Kibana installation (or specific provider/realm). Invalidating user session if their current role set is affected by the "concurrent account type sessions" requirement sounds acceptable. We retrieve user with their roles on every successful authenticate attempt, we know which roles are controlled by the requirement (through
Do we have an immediate need in those or we can consider adding them at a later stage?
That's true, but don't we do this already (and we'll have to) to constantly extend |
@legrego
I think storing the IP address initially would be sufficient. We can always specify an GeoIP Ingest Pipeline to populate this for us if we ever want or need this capability. @legalastic I'm seeing mixed messages online -- is an IP address considered PII? We are considering storing and associating a user's IP address with their Kibana session, for auditing purposes, but also for potential features down the line (e.g., limiting number of sessions per IP, or invalidating sessions if the user's IP address has changed). This data lives within the user's cluster, and never leaves the user's cluster. It will also be periodically cleaned up as sessions are invalidated/expired, but the lifespan of this data is TBD and user-configurable to an extent. Technically, under GDPR, an IP address is "personal data" where it is identifiable to an individual. (Parenthetically, I note the reference to geolocation (via MaxMind lookup) and would not consider that identifiable because the database there is too imprecise to provide address of a specific user.) As you may anticipate, the manner in which the IP address is used is also relevant to the analysis. Here, it looks like we would be using the IP address in a manner attributable to an individual. For my perspective--is the issue here whether to encrypt the IP address or is there another issue under review? |
Good call!
I like it!
I think making a note of this for a later stage makes sense.
Ah, I don't know why I wasn't thinking about Moving Pros:
Cons:
So, could we come up with some other reasonable mechanism to facilitate cleanups of stale session data? If so, we could keep |
@legalastic:
Yes, we would be associating the IP address with a username/individual, but we don't have plans in this initial phase to expose this data to end-users. However, users with sufficient privileges may be able to query this index directly, but those read privileges would have to be explicitly granted by one or more assigned roles. If it matters, we will not be storing the username in plain text, so querying the index directly will not allow someone to directly associate an IP address with a username, even if the IP address is stored in plain text.
Yeah, I'm interested to know if we need to encrypt the IP address. Doing so would prevent anyone with direct access to the Elasticsearch index from reading this data, but I expect it will also prevent us from being able to enrich this with geolocation data. |
@legrego I am going to see if we can get 15 minutes or so via zoom this week so that I can better visualize what you have in mind. My gut feeling is that the privacy implications here are pretty limited but I'd want to discuss live so I better understand. On the question of encrypting IP address--that may be as much a security-by-design question as it is a privacy-by-design question (e.g., if there are adequate controls over access to the Elasticsearch index then encryption is less of a requirement; plus, what is the risk to the customer/individual if the IP address were harvested.) I look forward to discussing in real time. |
@legrego to follow up on our call. There's no issue here from a legal perspective as the IP addresses remain in the cluster and only accessible to authorized users. The IP addresses are not being extracted or otherwise accessed by Elastic. As discussed, whether to encrypt is a judgment call as to the likely risk that an unauthorized user would get access to that information and, if they did, what the impact to the privacy rights of the individual would be. With regard to the latter---the impact would likely be slight since there is no readily available way for an unauthorized user to further be able to correlate to a person. With regard to the former, it sounds as if the product has security features designed into it that, if properly configured, would not permit unauthorized access. So the risk of unauthorized access is (by design) low. If I can provide more info, please let me know. |
Summary
Today, the Security Plugin stores user authentication information (username/password for
basic
or access/refresh tokens fortoken
,saml
,oidc
etc.) in the cookie that gets stored in the users browser. This cookie is encrypted with two-way encryption using a salt based on thexpack.security.encryptionKey
in the kibana.yml.This approach has a number of benefits (e.g. easy to scale) and drawbacks (e.g. we're hitting browser cookie size limit more and more). But more importantly, there are number of use cases we cannot really handle with the current approach, like #18162 or #53478.
This issue proposes using a more secure approach - maintaining server-side sessions in the Kibana backend. Instead of putting the encrypted authentication information in the cookie, the cookie would contain an encrypted session ID, which the server side would generate on first authentication, and store it alongside with all additional information in the Elasticsearch index. After session expiration (see below) or on explicit logout, it would be removed.
Where to store session information?
Since we started to discourage Kibana administrators from giving users access to
.kibana
index we can safely (to be assessed) use this index to store session information. Alternatively we can use a dedicated index similar to.security-tokens
index used by Elasticsearch.We'd likely want to store the session information in an encrypted form. Either leveraging
xpack.security.encryptionKey
for all sessions or separate unique keys for every session that'd be stored in the cookie, we'll need to find an acceptable security-performance trade-off. If we use single encryption key we may want to throw some AAD into the mix.When to clean up session information?
We can implement a number of optimizations to not overburden Kibana server with the session management, for example when user explicitly logs out or Kibana decides to do that on its own we'd not only remove this specific session, but also all other sessions that have expired (based on
xpack.security.session.idleTimeout
andxpack.security.session.lifespan
settings).In addition to that we can leverage
TaskManager
to schedule a periodic 24h task to do the cleanup as well.Also we may want to just mark sessions as deleted and physically delete them later for audit purposes.
What fields session information should include?
These are the first that come into my mind:
basic
, access/refresh token pair forsaml
or certificate fingerprint forpki
)Concerns
There are a number of concerns regarding Server-Side session comparing to the current approach:
.kibana
index size (only if we decide to use existing.kibana
index).kibana
index):.kibana
index backup.kibana
index can drop user sessions (not swap or alter though)pki
orkerberos
is used we can receive multiple "login" requests at the same time and we'll only figure out that they belong to the same user only after we talk to Elasticsearch that would issue different access tokens for both requests)Original comment by @skearns64:
Today, the Security component of X-Pack for Kibana encodes both the username and the password in the cookie that gets stored in the users browser. This cookie is encrypted with two-way encryption using a salt based on the `shield.encryptionKey` in the kibana.yml.This issue proposes using a more secure approach - maintaining server-side sessions in the Kibana backend. Instead of putting the encrypted username/password in the cookie, the cookie would contain an encrypted session ID, which the server side would generate on first authentication, and keep in memory, updating the expiration date with each valid request while the session was active. After session expiration, it would be removed.
I see two potential phases to this.
Phase 1 would be simply storing the session state in the Kibana server memory. The drawback to this approach is In scenarios where multiple Kibana instances are being load-balanced; the load balancer would have to ensure that the same users were always directed to the same Kibana instance (so their requests go to the Kibana server holding their session).
Phase 2 would be to store the session state in Elasticsearch, potentially in the .kibana index. I think doing this depends on LINK REDACTED , which would ensure that the .kibana index (or whatever index we choose to use here) was not accessible to end-users.
The text was updated successfully, but these errors were encountered: