Re: Avoiding PAM checks
Jan Safranek <[email protected]> Thu, 31 Jul 2014 09:40:16 +0200
| Newsgroups | gmane.network.open-pegasus.general |
|---|---|
| Message-ID | <[email protected]> |
On 07/30/2014 04:34 PM, Andreas Maier wrote: > > Karl, Jan, I have discussed the issue with a number of folks, and > that helped me to better understand how Jan's proposal works. > > I'd like to make the following comments, before I leave for vacation > (back at home from 8/16 on, back in the office from 8/25 on): > > Just to recap the overall approach: Upon successful authentication of > a CIM request, if the server supports the new feature, it invents a > session ID and sends that back with the CIM response. If the client > supports the new feature, it uses that session ID on subsequent CIM > requests. Upon receipt of a CIM request with such a session ID, the > server can decide whether it trusts the session ID sufficiently at > that moment to bypass the authentication check. > > I'm fine with that overall approach, but I kept the description > deliberately high level, because there are some considerations and > requirements: > > - It depends very much on the data that makes up the session ID. A > suggestion from one of our security folks was that the session ID be > a hash of (userid, timestamp, randon number, underlying SSL session > ID). It is definitely a requirement that the session ID cannot be > calculated by an intruder. For example, just using timestamp and > userid would probably be not sufficient. Keep in mind that the code > is open source, so the algorithm how exactly the hash is calculated > will be known, and the secret must be in the data, not in the > algorithm. Using the underlying SSL session ID for example ensures > that the same SSL session is still in place. Maybe that is too much > of a requirement, but it is something that needs to be carefully > considered. > Currently, the session ID is just cryptographically strong* random number, nothing else. Timestamp, source IP address and client user name are stored (and checked) in Pegasus memory, but are *not* transmitted in the session id. *) 15 bytes (120 bits), generated by RAND_bytes() call from openssl/rand.h. I've chose 15 as 'long enough' and divisible by 3, so it can be base64-encoded without padding. It can be longer, it's just one #define. I think that adding anything else to the session ID won't improve security in any way, it will just make it more predictable. We may store (and check) something on server, if we want. I would explicitly avoid checking SSL session ID, as the client may use different TCP connection (and thus SSL session) for subsequent request - that's very common in HTTP world, clients (e.g. pywbem) don't use Keep-Alive that much. > - The server must be able to determine the lifetime of the session > ID. The proposed cookie based approach would probably use the cookie > lifetime for that, but that could also be done otherwise. Can cookie > lifetimes be modified by a client? That would be bad. I would have a > better feeling if the lifetime was encoded in the session ID instead > of being a separate piece of clear data. Even if the session ID is a > hash (which cannot be unpacked), the server could remember (in > memory) which session IDs it has handed out at any point in time, and > match the session ID with an internal record of it that shows the > lifetime. The cookie lifetime is stored on server, client cannot influence it in any way. As I wrote above, it's not part of session ID, as it would make the ID more predictable. > - The server must be allowed to decide at any point that a normally > valid session ID is nevertheless dismissed, and that a new session ID > is created. The server can make that determination based upon nearly > everything, including suspicuous client behavior with otherwise > valid requests. If the server dismisses an incoming session ID, it > performs the normal authentication as if no session ID had been > provided by the client, and returns a new session ID. Well, there is no code for that, but if someone implements such detection logic, it's just one HashTable.remove() call to forget a session. which implies that the next request will go through proper authentication. > - As a result, the client must always use the session ID returned by > the last response, because the server could have recalculated it. Sure, that's how HTTP and my client patches work. > - how the session ID is transported between client and server, has a > number of options. It would certainly be some HTTP header. I have > seen extension headers used for that purpose, it does not necessarily > have to be a cookie. I find cookies generally suspicious, and don't > fully understand to what extent HTTP infrastructure (e.g. proxies) > can have a policy to not allow them, in which case a cookie based > approach would be limiting in such environments. Cookie is described as HTTP 1.0 extension in RFC 2109: HTTP State Management Mechanism, released in 1997. It has been revised several times and it is part of any decent HTTP implementation for ages. To be honest, I haven't looked for any other RFC for session management over HTTP, the cookie is really used everywhere. RFC 2616 (HTTP 1.1) says: Unrecognized header fields SHOULD be ignored by the recipient and MUST be forwarded by transparent proxies. So, client who do not support cookies SHOULD survive just with Basic authentication in every request, just like now. And proxies MUST forward the cookie. > - Obviously, it must be optional to support for both client and > server. Just to have it mentioned. The server is configurable. What benefit it has to turn it off on _client_ side? If a client receives a cookie, it indicates that the server supports it. The client just sends it back in subsequent requests. If the server decides that the cookie is not enough, the client processed 401 Unauthorized response as usual. > > - One important consideration is whether we want it to work with both > HTTP and HTTPS, and with all HTTP authentication mechanisms. Someone > needs to draw the matrix of HTTP/HTTPS with supported authentication > mechanisms, and state for which ones the session ID approach would be > supported. That may shape the design significantly. For example, if > we supported it only for HTTPS, the session ID would not need to be > encrypted. If we also wanted to support it for HTTP, we maybe want to > see it encrypted. As the session ID is just a random number, encrypting it on HTTP won't help much, especially without proper handshake protocol to exchange keys, which you don't have on HTTP. In addition, it looks quite funny that cookie should be encrypted, while Basic authentication (the only one that Pegasus supports now) sends user password unencrypted in a HTTP header. > - There are sufficient screws and decisions in that whole approach, > so that we cannot assume this is just an OpenPegasus addition. > DSP0200 documents all standard HTTP headers that play a role in > CIM-XML, and it would need to describe this new ability as well. Karl > and I are in the CIM-XML WG, and it should not take very long, once > we have agreed upon the details on how to do it. > > To me, the open points are: - how to calculate the session ID. This > could be a recommendation for servers to keep them secure, because it > is opaque for clients. - which mechanism to use to transport the > session ID between client and server. I hope I explained my design and implementation above, feel free to ask anything. Jan