Avoiding PAM checks Bug 9892

Andreas Maier <[email protected]> Tue, 26 Aug 2014 13:34:42 +0200
Newsgroups gmane.network.open-pegasus.general
Message-ID <OF5ED3651A.BD6689F7-ONC1257D40.0039F159-C1257D40.003F9A63@de.ibm.com>
On the two open issues stated by Karl:

> 1. Exactly what should be in the sessionID.

Having read http://unixpapa.com/auth/homebuilt.html meanwhile, I htink the
proposal to use a random number as the session ID, and to store any other
pieces of information in memory on the server side, is the way to go.

> 2. Use of the cookie headers to pass this authentication
>    state information (sessionID) versus other means to
>    pass the information.

Having read the latest cookie RFC (RFC6265), I guess I need to correct my
bias against cookies and feel OK about using them.

The only possibly remaining concern is a general "fear of cookies" that
others could have. Section 3.3.1.2 in this article
http://unixpapa.com/auth/homebuilt.html describes that effect nicely:

   Cookies also suffer from bad press. Whether or not there is any
   justification at all for the poor reputation of cookies, it should be
   clear that using cookies instead of query parameters in authentication
   applications is only an implementation difference - both methods
   maintain the exactly same data. So there is no rational reason for the
   user to worry more about one than the other. Yet if you use cookies,
   there are still some users who will worry about privacy violations and
   some who will avoid your site entirely. Because of cookie-related
   security holes like this, some users routinely surf with cookies
   disabled (though disabling javascript is probably the more sensible
   solution). Whether justified or not, this fear of cookies is a factor
   that must be weighed when choosing an authentication method.

But as I said, I'm ok with using cookies as the mechanism. One other
mechanism I have seen in one of our products is to use an HTTP extension
header for the session ID.

As for details within the Set-Cookie header, it seems to me:
   - we should not set any expiration (Expires & Max-Age attributes),
   - no Domain attribute (the default described in RFC6265 is for the
      client to send the cookie back to the origin server),
   - no Path attribute (the default is for the client to assume the
      "directory" of the request-uri's path component.
   - cookie name: Although it is a valid argument that the cookie name can
      be anything because the client just returns it, I would still nail
      down the name (e.g. to "SID"), if only to allow for additional use of
      cookies in the future.
   - cookie value: I like base64 encoded, but I'm not sure nailing it down
      to 15 bytes (unencoded) is felt to be long enough for everybody. How
      about requiring a minimum length of 15 (unencoded) bytes?
   - We should set the Secure attribute, if only to make it explicit that
      the cookie is not to be used with HTTP. Also, RFC6265 recommends that
      in its subclause 8.3. I am aware that this is supposed to control
      generic browsers, so we could require that WBEM clients operate to
      different rules, but I think those rules should be as close as
      possible to those of generic browsers.

I would like to better understand the implications of the two alternatives
of (1) using the session ID for just one more request, or (2) for a number
of subsequent requests, until the server chooses to expire it.
Partricularly how the performance gain of (2) would be weighed against its
lowered security.

I read through the cookie vulnerabilities described in subclause 8 of
RFC6265, and it seems to me we would be ok for all of them (at least for
(1), above), but I'd like everybody to read through those sections and make
up your own minds.

Otherwise, we should be pretty close to a change request to DSP0200, with
specific text.

Andy

Andreas Maier
IBM Senior Technical Staff Member, Systems Management Architecture & Design
IBM Research & Development Laboratory Boeblingen, Germany
[email protected], +49-7031-16-3654
________________________________________________________________________
IBM Deutschland Research & Development GmbH
Vorsitzende des Aufsichtsrats: Martina Koederitz
Geschaeftsfuehrung: Dirk Wittkopp
Sitz der Gesellschaft: Boeblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294

----- Forwarded by Andreas Maier/Germany/IBM on 26.08.2014 12:32 -----

From:	Karl Schopmeyer <[email protected]>
To:	Jan Safranek <[email protected]>, Andreas
            Maier/Germany/IBM@IBMDE, OpenPegasus Developer mailing list
            <[email protected]>
Date:	31.07.2014 19:47
Subject:	Avoiding PAM checks Bug 9892



My real concern was that the design depended on the cookie header which
without some extension to the DMTF protocol specs meant that OpenPegasus
had a "non-compliant" extension as part of its protocol for at least
cim/xml
and that should be considered for the other protocols also (wsman,
etc.). It is
HTTP compliant but not the DMTF specifications.

Given that Andy has agreed that we could propose some part of this to
the DMTF cim/xml
team as a proposed extension, and Jan's responses below which really
represent
a fairly simple solution that only passes the temporary ID back to the
client
in the cookie header (everything else is stored in the server including the
timeout information) which the client must return to ask the server to
bypass
PAM I think we are down to a couple of issues:

1. Exactly what should be in the sessionID.
2. Use of the cookie headers to pass this authentication state
information (sessionID) versus other
     means to pass the information.


SessionID

1. Andy notes that the the exact form of the SessionID is up for
discussion but that
was based on the SessionID carrying real information whereas Jan defined
it as
just a random number ID (all real information is only in the server).
It would
appear that the simple ID proposed is really adequate and that the
server may elect to
test other information received in WBEM requests containing a cookie (IP
address, etc.)
to what level of security it desires.

2.

Protocol Basis for passing session information between server and client

It is clear from the documentation that while there are many recognized
deficiencies throughout
the life of the cookie, it is the dominate mechanism for passing any
type of state information.

My only concern was that we do not want anything that cannot be met by a
conformant WBEM
client (i.e. Open Pegasus secret sauce).  Thus, if we accept that the
concept of the cookie is
the logical way to pass state information like this, then the
significant additional requirement on
the DMTF specifications is that a WBEM client may return a cookie if it
receives a Set-Cookie:
response from the WBEM server and that a WBEM server may include a
Set-Cookie header in
a WBEM response.

This is a specialized and specific use of the cookie header concept. As
such it would appear:

1. The cookie in the WBEM client has a life of a session where the
session is defined by the server and
     possibly limited by the WBEM client.
     If a Set-Cookie: header is received by the client it sends the
cookie back to that server with the subsequent
     operations for the same session and can then discard the cookie.
This is more specific than
     the general use of cookies in a browser/web server environment.
     As such, there is no need for the expiration date option (Expires=)
or the other optional components that
     are defined in RFC 6265 at least for the patches proposed as the
Pegasus implementation.

2. The concept of session is completely by the server. It creates a
session once it
     has validated the request, creates the sessionID, times out the
session, and has a way
     to tell the client when the session has timed out ( error 401,
Unauthorized)

If defined in an extension to the cim/xml specification, the requirement
would simply be that:

     a. The WBEM Server and WBEM client may use the HTTP cookie header
fields as defined in HTTP
         specifications. Note that the original specification was RFC
2109 which was superceeded by
         2965, which was, in turn, superceeded by 6265 so we should be
referenceing 6265 I think.
         This defines the Cookie: and Set-Cookie: header fields

b. A WBEM server may receive a WBEM request message that includes a
cookie header field
         as defined in the HTTP specifications that includes cookies
defined in a previous WBEM
         response message

     c. A Client that receives a WBEM response containing a set-cookie
header should
         return that cookie in the subsequent requests for the same
session.

     d. A Server may include a cookie header in a cim/xml response
containing one or
         more cookies based on the HTTP specification.

In fact the only real changes to the DMTF specification are probably
that a WBEM server response
may include a cookie header (set_cookie:) and if it does, the WBEM
client may include that cookie
in subsequent requests.

Note that the current patch defines the cookie name as "PEGASUS_SID"
which is an OpenPegasus
defined name and pretty much ties this particular cookieto OpenPegasus.
Since the cookie name is
server generated and is only to be used to send the cookie back to the
server with the next request
for the same session, the actual name is effectively meaningless.




On 07/31/2014 02:40 AM, Jan Safranek wrote:
> 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
>