Skip to content
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

Define a lifetime for DTLS session #617

Closed
sbernard31 opened this issue Apr 24, 2018 · 24 comments
Closed

Define a lifetime for DTLS session #617

sbernard31 opened this issue Apr 24, 2018 · 24 comments

Comments

@sbernard31
Copy link
Contributor

The TLS 1.2 spec says: "An upper limit of 24 hours is suggested for session ID lifetimes, since an attacker who obtains a master_secret may be able to impersonate the compromised party until the corresponding session ID is retired."

We should implement this lifetime, making it configurable and setting it by default to 24h.
A short term solution could be to make DTLSConnector(final DtlsConnectorConfig configuration, final ResumptionSupportingConnectionStore connectionStore) public. This way anyone could implement its own store and so add session/connection lifetime.

(This seems to be a community needs)

@boaks
Copy link
Contributor

boaks commented May 2, 2018

https://tools.ietf.org/html/rfc5246#appendix-F.1.4

Sessions cannot be resumed unless both the client and server agree.
If either party suspects that the session may have been compromised,
or that certificates may have expired or been revoked, it should
force a full handshake. An upper limit of 24 hours is suggested for
session ID lifetimes, since an attacker who obtains a master_secret
may be able to impersonate the compromised party until the
corresponding session ID is retired. Applications that may be run in
relatively insecure environments should not write session IDs to
stable storage.

So very first, we should define, if this applies to "Resuming Sessions" or also to "connections". Though

public synchronized Connection get(final InetSocketAddress peerAddress) {
	return checkValidity(connections.get(peerAddress));
}

seems to remove not only sessions, when they are tried to be resumed, it removes also "connections". Therefore I would guess, that this may have some "unwanted side effects". One I see, is that in cases of "expired connections", terminating the connection is not longer indicated to the other peer.

@sbernard31
Copy link
Contributor Author

It was obvious to me that when a session expired, correlated connections expired too.

So, I looked deeper on this and I didn't find clear resource about that but now I was not so sure anymore...

Here a discussion about "why a session cache lifetime ?"
What I understand is "session lifetime aims to help for perfect forward privacy and for lifetime-limited credentials"
If this is the case, having long lived connection is an issue too, right ?

So, what should we do ? Define 1 lifetime for session and 1 lifetime for connection ?
(with connection lifetime < session lifetime)

@boaks
Copy link
Contributor

boaks commented May 3, 2018

Yes, I would go for two values (0 for disabled and NO "<" defined relation between the two values).

@sophokles73
Copy link
Contributor

I am not sure if I can follow. Looking at it from a server's perspective, I would argue that it is irrelevant whether a session is established and in use or whether it is resumed by a client at a later time. My understanding of the spec is that the lifetime of the session ID of the established session must/should not exceed 24h. Based on that I would think that the server terminates an established session once it has exceeded the limit and also reject attempts from clients to resume the session. The latter could be implemented by simply evicting all of the connection's state from the ConnectionStore. Or am I mistaken?

@sbernard31
Copy link
Contributor Author

I was understanding the same but after the @boaks' remarks I made some research and I concluded that this should probably not be interpreted in that way. (see all the links in #617 (comment))

An upper limit of 24 hours is suggested for session ID lifetimes, since an attacker who obtains a master_secret may be able to impersonate the compromised party until the corresponding session ID is retired.

Session ID/master_secret is about "impersonate a master_secret" and so this only about session resumption.

I found nothing about a connection lifetime, but this seems clear that a long lived connection could introduce some issue about security especially about credentials expirations.

So, we conclude that maybe this makes more sense to define 2 lifetime (one for connections and one for sessions ID/Session Ticket)

I see benefits about that from a client perspective, this ensure that a connection established will not be closed some seconds later.
I mean imagine that a client try to resume a session which will expire in 10s, it will established a connection which will live only 10s ... not so good ! (I know we can imagine a kind of threshold for resumption but I found 2 lifetimes more simple)

@boaks
Copy link
Contributor

boaks commented May 3, 2018

I guess, the issue with TLS is, that caused by IDLE timeouts or other stuff, the TCP connection is terminated anyway and mostly earlier. Additionally, even, if you can access the connection "secrets", it would be hard to use them outside that TCP connection. Therefore the "connection secrets" seems to be not of interest in TLS.
So ... a next question to the ietf list :-).
And so I think, configuring it should do it.

@boaks
Copy link
Contributor

boaks commented May 3, 2018

Just to mention:
I'm not sure, why the "master secret" or "connection secret" should be easier to obtain from a device than the credentials. If these credentials would be protected by a "password on startup", OK, but for devices this seems to be rare.
So, for all, who don't use a "smart secure store", which only stores the credentials but not the "xyz secrets", this timeout seems not to make sense.

@sophokles73
Copy link
Contributor

So, we conclude that maybe this makes more sense to define 2 lifetime (one for connections and one for sessions ID/Session Ticket)

The lifetime of an established session currently has an upper boundary determined by the session's sequenceNumber counter. Once it has reached 2^48-1 the DTLSSession.getSequenceNumber() method throws an IllegalStateException. However, this exception is not caught anywhere and thus does not lead to the termination of the session, which I believe it should.

I do agree, though, that it makes sense to disallow the resumption of a session based on a configurable maximum session age and use 24h as the default.

@boaks
Copy link
Contributor

boaks commented May 4, 2018

The lifetime of an established session currently has an upper boundary determined by the session's sequenceNumber counter.

In my opinion, this limits the "connection", because "resuming" a session would reset that sequence number.

I do agree, though, that it makes sense to disallow the resumption of a session based on a configurable maximum session age and use 24h as the default.

As long as it is implemented configurable, I'm OK with it, even, if I belief, as written above, that for devices the security in too many cases will not be increased, as long as credentials and "master secret" are not handled different.

@sbernard31
Copy link
Contributor Author

I'm not sure, why the "master secret" or "connection secret" should be easier to obtain from a device than the credentials. If these credentials would be protected by a "password on startup", OK, but for devices this seems to be rare.
So, for all, who don't use a "smart secure store", which only stores the credentials but not the "xyz secrets", this timeout seems not to make sense.

It seems not right to me :

  1. If you are using cipher which bring Forward Secrecy, steal the credentials will not allow us to decrypt a captured traffic.
    Steal the "master secret" will only allow to decrypt the session traffic.
    If you always use the same session/master secret, you can decrypt all the traffic and so lost the interest of using a PFS cipher.

  2. if you never expire the session you can resume it all the time and use a expired certificate for ever.

  3. I don't know if this is appropriate to our cipher and DTLS 1.2 but I know there is attack based on capturing/lot of traffic, using long-lived session/connection allow this kind of attack.

@boaks
Copy link
Contributor

boaks commented May 4, 2018

  1. how should this be related to the timeout? For me, it indicates, to protect your master secret even better, than the credential. But then this timeout is useless, or?

  2. a session timeout will not really work as proper as a "credential base" session termination.
    See also InMemoryPskStore should have the ability to remove a PSK  #189

  3. "With a modern block cipher with 128-bit blocks such as AES,"

Just to say, I'm not against such a timeout, but FMPOV it's wrong to tell the people, that this will make a device more save.

@sbernard31
Copy link
Contributor Author

Just to say, I'm not against such a timeout, but FMPOV it's wrong to tell the people, that this will make a device more save.

I get it, but if we agree this is useless this is even better to do nothing :-D, so I try to have a more accurate view about that.

My vision for now :

  1. A short-lived "master secret" aims :
    1.1 enhance confidentiality of past conversations.
    1.2 limit the time you can use the comprised key.
    If you always use the same master secret, stealing only once a "master-secret" you can decrypt all the past conversations and usurp the identity for ever.

  2. I was talking about certificate,  InMemoryPskStore should have the ability to remove a PSK  #189 refer to PSK. What could be a proper way to handle certificate expiration or revocation ?

  3. I didn't talk about this attack but about kind of attack like this, I mean using a traffic capture. I'm ok that's not a strong argument.

@boaks
Copy link
Contributor

boaks commented May 7, 2018

My vision: The degree of security is mostly complex :-).

  1. only applies currently to devices, which use x.509 or RPK. So only with these cipher suites, someone may consider this as more secure.

  2. A server may proactive remove certificate based DTLS session on the expiration of the used certificates.

So in my opinion, it is left to the client to "terminate" sessions/connections on his level of security.

@sbernard31
Copy link
Contributor Author

here a discussion about session ticket lifetime in TLS 1.3

@sbernard31
Copy link
Contributor Author

I would like to re-talk/re-work about this feature. I read this discussion again and I'm still not sure about the direction we should go... (not for 2.0.0-M15 :))

It seems there are 4 options :

  1. do nothing because all of this doesn't make sense (I don't really share this idea)
  2. adding 1 lifetime for Session and when session expired connection expired too.
  3. adding 1 lifetime for Connection and 1 lifetime for Session. (OpenSSL seems to have a session lifetime... I find nothing about Connection lifetime ... which sounds strange to me because I can not get the idea about just limiting session lifetime unless session expiration close connection?)
  4. a lifetime is not enough and we should think about an API to let user expire connection or session as they want (based on time, credential changes, ...)

By the way I add this paper, which talks a little bit about session lifetime and PFS.

@boaks boaks modified the milestone: 2.0.0-M15 Apr 9, 2019
@boaks
Copy link
Contributor

boaks commented Apr 9, 2019

May be 4. is also related to issue #189 .

The idea to solve issue #189 is to iterate over the connections "unsynchronized" and use the cid to overcome "race-conditions" when accessing the connections. I didn't start with that.

@sbernard31
Copy link
Contributor Author

Does it means you think that 4 is the better option ?
I feel this is the more flexible way but maybe not so easy to use or implement than 2. or 3.

@boaks
Copy link
Contributor

boaks commented Apr 9, 2019

Yes, I think 4 is the better option.
We will see, how hard it gets :-).

@sbernard31
Copy link
Contributor Author

Should we close this issue ?
Or should we wait that :

To include the session cache requires to extend that cache as well.

(from : #1007)

@boaks
Copy link
Contributor

boaks commented Aug 12, 2019

The "cache" is used for too different things.
"cluster - remote session cache": in that case, it's more about to terminate a session in the cluster. It would not make sense, to load all session to a local node, just to terminate them there, if other nodes may have also associations/connections for that session. That case mainly stopped me from spending efforts in it.

@sbernard31
Copy link
Contributor Author

sbernard31 commented Aug 12, 2019

I try to resume :

Regarding RFCs and discussion above, we have 2 main concepts : connection and session. Each one could have a lifetime.

With current implementation :

1. If Session cache is NOT used.

Session and connection lifetime are tied.

You can implement a kind of session lifetime using new DTLSConnection.startForEach() and DTLSSession.getCreationTime(), but you can not just kill the session and keep the connection, you kill both at the same time.

You can not really implement a connection lifetime because you don't know the connection creation time. If we have this data, we could implement a kind of connection lifetime but killing the connection will also kill the session.

2. If Session cache is used.

Session and connection lifetime are separated.

"cache" will probably used persistent technology (database/redis), so it makes sense to me that the store handles "expiration" itself.

You can implement a real session lifetime using your own SessionCache implementation and DTLSSession.creationTime. This will not kill linked connection. Up to the user to clean if wanted using DTLSConnection.startForEach() (or to define a lifetime on connection too ?).

You can not really implement a connection lifetime because you don't know the connection creation time. If we have this data, we could implement a real connection lifetime with DTLSConnection.startForEach(). This will not kill linked session as session will not be removed from SessionCache.

Do I well understand ?

@boaks
Copy link
Contributor

boaks commented Aug 12, 2019

The DTLSSession has a

public String getLastHandshakeTime() {
	return handshakeTimeTag;
}

I think, that's the connection/association time.

@boaks
Copy link
Contributor

boaks commented Aug 12, 2019

Just to mention:
With the general iterator approach, PRs with extended possibilities will also be welcome.
FMPOV, it was more important to have such a general approach then to have all variants already in place.

@boaks
Copy link
Contributor

boaks commented Jan 17, 2023

Hibernating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants