-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 All,
Tomcat stores sessions without any encryption and/or authentication, and anyone with write-access to the session-store can poison a session and mount an attack. This kind of attack is (arguably appropriately) declared to be outside of the scope of Tomcat's responsibilities, because the system administrator should arrange for appropriate access-controls to whatever storage medium is being used. Note that sessions can also be read from such a store, of course, but I'm more concerned with a privilege-elevation attack, here and not a loss of privacy. It turns out that the solution to one problem can solve them both. If you want to be as paranoid as possible (and why not?), you'll want to make sure that your session persistence mechanism isn't readable by anyone but Tomcat. I'm sure there are use-cases for making those session stores readable outside of Tomcat, but then again, those people aren't asking Tomcat to provide secure session storage. It would be simple to encrypt (or sign) the session-data and decrypt (or validate) the data coming back in when reloading. Of course, it would be a deployment headache because it's another shared secret that needs to be deployed to all servers in e.g. a cluster. I'll be talking to Rémy about his cloud provider for clusters to see if we can do things like trade-around cluster-encryption keys via a cloud manage r(e.g. Kubernetes), and then it seems logical that we could do the same kind of thing for the session manager, too. Environments without such orchestration would have to arrange to distribute their shared secrets in some other way. This could be implemented either at the Store level or -- even better IMO -- at the StandardSession level, since StandardSession.wrireObjectData/StandardSession.readObjectData can do anything it likes to its own data such as signing or encrypting. No interfaces would have to change. I didn't see an opportunity to install any kind of shim/interceptor/decorator into the existing pipeline to add this "outside" of either the Session or the Store without any API change, so the above idea seemed to me to be the best way to look at implementing such as thing. The interface for Session doesn't help at all, since this facet (session persistence) is only introduced at the StandardSession level. Also, the interface is basically: writeObjectData(ObjectOutputStream) readObjectData(ObjectInputStream) In order to provide arbitrary manipulations, we could introduce a new interface: interface DataMassager { writeObjectData(ObjectOutputStream) readObjectData(ObjectInputStream) } Then we just wrap these things around the existing implementations. Maybe the DataMassager is a field in StandardSession. I generally like the idea of an interceptor, but with a stream-based API -- especially when the stream class isn't very generic -- it's difficult to do. If we were able to change from Object(In|Out)putStream to (In|Out)putStream or just simply writeObjectData(byte[]), then various interceptors could mutate the data arbitrarily on the way in or out (or, likely, both). If we could get away from Object(In|Out)putStream, I think that would be a win. We might be able to do that by introducing new API methods in Session.java: public void writeObjectData(OutputStream); public void readObjectData(InputStream); Those can, by default, just wrap an Object(In|Out)putStream around those streams and call the existing code. But other implementations could use the generic streams directly. But without an API change, I think we are going to have to have a single session-data mutator object. Stacking things up will have to be an exercise for someone who wants something beyond the complexity I expect to introduce, which is simply to encrypt data in the persisted session-store. If Tomcat encrypts session data with a symmetric key (shared with any other Tomcat instance which would need to read the session data from the same store), then we can guarantee that session data loaded by Tomcat was generated by Tomcat. (Or at least was generated by code which knew the key. We can only do so much.) Such encryption protects the data from being viewed by unauthorized parties or from being forged and/or manipulated. The only thing I can think of that it will not prevent is replay attacks: grabbing a copy of a stored session and then re-injecting it into the session-store. I'm not sure there is an attack against Tomcat hidden in there, but certainly there is an attack against the application in there. Applications could version sessions or add timestamps to things as a mitigation against session-replay attacks. Tomcat could add replay-mitigations in a few ways, but I'm not entirely sure these are worth is. In the spirit of academic navel-observation, let me lay out a few ways that could be done. First, we could version sessions. Each time a session is written-out, its version number is incremented. Or a timestamp is added. When loading the session, the in-memory session version or timestamp is consulted and anything that is older than current will be ignored. This is great as long as Tomcat has the session information in memory already, which is NOT a given. Other thoughts I had included using file-metadata of some kind as a corroborating factor, but if this is going to live in a serialization method, then there is no context of a file or anything else like that present. So whatever mechanism is being used needs to be stored in the serialized session data itself. I think that's enough for now. So the questions are: 1. Does anyone really want Tomcat to be worried about this stuff? I know the answer is "some people care" but I want to get a sense of how many actually care. So if you think this would be a good thing to implement in one way or another, please speak up. 2. If we implement this, is it okay to change the API to do so? I think we can do this in a backward-compatible way so that we don't have to e.g. use an ObjectOutputStream to write a byte[] which has been encrypted after using another ObjectOutputStream to generate those bytes for storage. 3. Is encryption "enough", or should we try to implement some kind of replay-mitigations? I don't think we'll ever be able to completely close this hole because (a) Tomcat can't be expected to have a priori information about the session before it's being loaded (e.g. after restart) and (b) all the validation information must be inside the stored session data. I can't think of a way to avoid a replay attack short of maintaining yet another database of session-versions for validation. I can see a man in the corner wearing an "Over-Engineering Police Force" uniform staring at me intently. Thanks everyone for reading this and providing any feedback you may have . - -chris -----BEGIN PGP SIGNATURE----- Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/ iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl7erdQACgkQHPApP6U8 pFhc9w/9E55cFOAkz6uYwhdFlAYKZQSjS2xdpsavfZzLO0EE2InosBDKlKvxblW2 pnoPGwFIrI5gGyccONlmOB96XtQYsgYDfhoN854MwryAatc0hOmwItNJN39fhj0M Ae2UovjqkwpgLy5MFP6topb8KT6cVj1jCmKSDLLMIx1bz8VhKNjDZPcfzqOM0PO/ /kshyUrsmUC2Q3FSab+dhEGcOz4hoJRGnmFYn2NjG9FzXn5+sOJWll3yHvlfVFZp 9l9OZfZnUvfJQRYtzGZBpqpZJCKUDboN1+/1xaHFtZPjyYawNUiYUkkNgMBzUz2Q 8uSYd2+tCfxD6CQfWi/aFUqxJWuJ/ehoYQ0z2phlbAxEfWuUgMryvqmJrsL+MVOO s0nm31/+2oRrhjspjsJE45Xuvx6EMMy52nxUw3IR6YZr9JEKEnsXRvjGhOZjAVG+ Jc1pBskJo6L0CRIOWrdhbRVL5i74xZbsYqvofwbGhTshjZPdPfMh876sVgIdKTUZ lqoWt0aqsTjmdnPbTOs6UgKu25iTI2u3A2O4GRlpPDFaubL8nsIfhpvIa8679lYx YCGtkx5ieErCqla4Wfo/MdvEHcoGmOcdwRyx7OLKN6CsIELsdt98UpPT+scTogF2 0dLy8o7RxG9tLrAIGIrK3cCGCsAXIypA3rXFnR2CuwNp84LXTHU= =0NFi -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org