• Always prompting for OTP

    From BuzzSaw Code@21:1/5 to All on Tue May 10 11:47:55 2022
    I'm trying to understand if the behavior I'm seeing is by design or a bug.

    Using the 1.19.3 release along with Russ Allbery's pam_krb5, no matter what
    options are set for pam_krb5, when using one of our accounts setup for RadiusOverOTP, the krb5 library prompter asks for the OTP token.

    Tracing the calls and adding our own debug statements we see that the
    password is being passed in to the Kerberos library routines.

    It seems like the original credentials that were passed in, which is the
    valid OTP "pin+password", are tossed by the krb5 library routines once the
    KDC responds asking for preauth and the anonymous FAST conversation is done
    no matter what.

    Is there no way to tell the library to use the credentials we gave you
    without asking for more information?

    V/r,
    DC

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Hudson@21:1/5 to BuzzSaw Code on Tue May 10 13:02:26 2022
    To: kerberos@mit.edu

    On 5/10/22 11:47, BuzzSaw Code wrote:
    I'm trying to understand if the behavior I'm seeing is by design or a bug.
    [...]
    It seems like the original credentials that were passed in, which is the valid OTP "pin+password", are tossed by the krb5 library routines once the KDC responds asking for preauth and the anonymous FAST conversation is done no matter what.

    This is by design. The basic Kerberos protocol does not reveal the
    password to the KDC, but FAST OTP does reveal the OTP value (encrypted
    within the FAST channel). So for libkrb5 to transparently send the
    password to the KDC when the KDC asks for FAST OTP would have security implications.

    pam_krb5 could work around this decision via its prompter callback, and
    that might be reasonable to implement as an option.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BuzzSaw Code@21:1/5 to Greg Hudson on Tue May 10 13:51:02 2022
    Copy: kerberos@mit.edu



    This is by design. The basic Kerberos protocol does not reveal the
    password to the KDC, but FAST OTP does reveal the OTP value (encrypted
    within the FAST channel). So for libkrb5 to transparently send the
    password to the KDC when the KDC asks for FAST OTP would have security implications.


    I guess I'm missing the security issue if I'm asking it to send the
    credentials originally supplied in that FAST channel. We're
    using anonymous FAST so I didn't expect (or want) it to send those outside
    that channel.

    pam_krb5 could work around this decision via its prompter callback, and
    that might be reasonable to implement as an option.


    I started looking at that by trying to trace down where the library removes
    the password but haven't been able to follow all of the code (yet).

    A bad side effect of this behavior is that the calling PAM module never
    gets that OTP value so it isn't available for other modules in the stack,
    so they too prompt for credentials because they think the password has not
    been entered yet.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Russ Allbery@21:1/5 to BuzzSaw Code on Tue May 10 11:05:45 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    BuzzSaw Code <buzzsaw.code@gmail.com> writes:

    A bad side effect of this behavior is that the calling PAM module never
    gets that OTP value so it isn't available for other modules in the
    stack, so they too prompt for credentials because they think the
    password has not been entered yet.

    What behavior do you expect here? For the full OTP+password string to be carried over to other modules in the stack, or only the password?

    If the latter, I believe this inherently requires that the pam_krb5 module
    know to disassemble the password (which would probably also solve your
    other problems at the cost of more complexity in the PAM module).

    --
    Russ Allbery (eagle@eyrie.org) <https://www.eyrie.org/~eagle/>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Russ Allbery@21:1/5 to BuzzSaw Code on Tue May 10 11:49:23 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    BuzzSaw Code <buzzsaw.code@gmail.com> writes:

    We want the full OTP+password string just passed without modification.

    Ah, okay, so then in theory the problem could be solved entirely within
    the Kerberos libraries, although I haven't wrapped my mind around the
    problem Greg identified.

    It would also be nice if when we use try_first_pass/use_first_pass/force_first_pass options with pam_krb5
    that it actually did that in the OTP case without the extra prompt.
    no_prompt doesn't help as the password doesn't stay on the stack.

    I'm assuming this is because the Kerberos library doesn't think that the passed-in password can be sent after the FAST negotiation and therefore re-prompts internally? I'm not sure I entirely understand the logic flow
    here.

    --
    Russ Allbery (eagle@eyrie.org) <https://www.eyrie.org/~eagle/>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BuzzSaw Code@21:1/5 to Russ Allbery on Tue May 10 14:40:41 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    On Tue, May 10, 2022 at 2:05 PM Russ Allbery <eagle@eyrie.org> wrote:

    BuzzSaw Code <buzzsaw.code@gmail.com> writes:

    A bad side effect of this behavior is that the calling PAM module never gets that OTP value so it isn't available for other modules in the
    stack, so they too prompt for credentials because they think the
    password has not been entered yet.

    What behavior do you expect here? For the full OTP+password string to be carried over to other modules in the stack, or only the password?


    We want the full OTP+password string just passed without modification. It would also be nice if when we use try_first_pass/use_first_pass/force_first_pass options with pam_krb5 that
    it actually did that in the OTP case without the extra prompt. no_prompt doesn't help as the password doesn't stay on the stack.

    In this use case we're dealing with systems that use OpenPAM vs Linux-PAM
    so we don't have any of the more advanced syntax to skip modules. We
    can't use 'sufficient' to immediately jump out of the stack as we want some
    of the later modules to run.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BuzzSaw Code@21:1/5 to Russ Allbery on Tue May 10 14:57:53 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    On Tue, May 10, 2022 at 2:49 PM Russ Allbery <eagle@eyrie.org> wrote:

    BuzzSaw Code <buzzsaw.code@gmail.com> writes:

    We want the full OTP+password string just passed without modification.

    Ah, okay, so then in theory the problem could be solved entirely within
    the Kerberos libraries, although I haven't wrapped my mind around the
    problem Greg identified.


    Same - I started walking through the code but haven't tracked down the
    point where it tosses the original creds.



    It would also be nice if when we use try_first_pass/use_first_pass/force_first_pass options with pam_krb5
    that it actually did that in the OTP case without the extra prompt. no_prompt doesn't help as the password doesn't stay on the stack.

    I'm assuming this is because the Kerberos library doesn't think that the passed-in password can be sent after the FAST negotiation and therefore re-prompts internally? I'm not sure I entirely understand the logic flow here.


    Me either - haven't been able to fullyl grasp the flow.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Hudson@21:1/5 to Russ Allbery on Tue May 10 15:46:26 2022
    To: buzzsaw.code@gmail.com (BuzzSaw Code)
    Copy: kerberos@mit.edu

    On 5/10/22 14:49, Russ Allbery wrote:
    We want the full OTP+password string just passed without modification.

    Ah, okay, so then in theory the problem could be solved entirely within
    the Kerberos libraries, although I haven't wrapped my mind around the
    problem Greg identified.

    I will try to explain again.

    The Kerberos protocol was designed to be somewhat resistant to phishing.
    If I set up a rogue KDC and somehow convince clients to authenticate,
    the clients do not simply send me their passwords. This resistance
    isn't perfect; by asking for encrypted timestamp I can probably get the
    client to send a ciphertext that I can use to conduct an offline attack,
    and I can probably influence the client to use a fast string-to-key
    function by pretending to only support an older encryption type. But
    it's still a goal.

    FAST OTP does not have any phishing resistance, at least in the mode
    that is used in practice. Whatever the user types in as the OTP value
    is simply sent to the KDC to be inspected raw. On the positive side,
    FAST OTP can only work over FAST, and one can presume that the FAST
    armor key was obtained in a way that authenticates the KDC to the
    client. So it's not as easy to receive client authentications as a
    rogue KDC as it would be in the original protocol. But depending on the scenario it might still be possible. pam_krb5 has some idea of the authentication scenario (it's a system login of some kind), but libkrb5
    does not.

    If an OTP client preauth module used the password as the OTP value, that
    would make it easier for a KDC to completely subvert the phishing
    resistance of the original Kerberos protocol. Again, prompting
    separately isn't a perfect solution as users confronted with an "Enter
    OTP Token Value" prompt are as likely as not to simply re-enter the
    password. But it would still be worrisome.

    I'm assuming this is because the Kerberos library doesn't think that the passed-in password can be sent after the FAST negotiation and therefore re-prompts internally? I'm not sure I entirely understand the logic flow here.

    The FAST negotiation is irrelevant, except insofar as it makes the
    design of FAST OTP possible. Client preauth modules implementing OTP mechanisms simply don't consider the Kerberos password to be the same as
    an OTP value, so they ask for the OTP value via the responder or prompter.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Russ Allbery@21:1/5 to Greg Hudson on Tue May 10 13:54:05 2022
    Copy: buzzsaw.code@gmail.com (BuzzSaw Code)
    Copy: kerberos@mit.edu

    Greg Hudson <ghudson@mit.edu> writes:

    The FAST negotiation is irrelevant, except insofar as it makes the
    design of FAST OTP possible. Client preauth modules implementing OTP mechanisms simply don't consider the Kerberos password to be the same as
    an OTP value, so they ask for the OTP value via the responder or
    prompter.

    Oh, I think this was the bit that I was missing. I was for some reason assuming that the Kerberos library itself understood that part of the
    thing passed in as a "password" was actually an OTP value and the other
    part was a password, but it sounds like I was wrong to think this, and
    instead the entire "password" is sent via RADIUS and it's the RADIUS
    server that takes it apart into an OTP value and an actual password?

    And therefore, because of that, the Kerberos library declines to send a password passed in as an argument to krb5_get_init_creds_password to the
    RADIUS server, and always forces a separate prompt, because it is really designed for the case where the password and OTP are separate and entered separately at two different prompts, the second (for the OTP) triggered by
    the preauth mechanism?

    If I have this right, it feels like the root problem is the combined
    password mechanism that overloads the password field to carry unrelated additional information, but unfortunately that may be forced by the number
    of protocols that are entirely unable to deal with additional PAM prompts.

    --
    Russ Allbery (eagle@eyrie.org) <https://www.eyrie.org/~eagle/>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Russ Allbery@21:1/5 to BuzzSaw Code on Tue May 10 14:12:34 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    BuzzSaw Code <buzzsaw.code@gmail.com> writes:

    But that prompt is a callback to the prompter routine in pam_krb5 passed
    in so I could bypass that prompt by just force feeding the "password"
    into the response structure right ?

    Yes, you can intercept it inside pam_krb5. It's really ugly from a
    pam-krb5 architecture perspective, though, so I'm not sure I'd want to incorporate that upstream.

    I feel like we went through a very similar problem with the use_pkinit
    option and we came up with some solution that didn't require doing this response injection thing, but I seem to have swapped all of that out of my brain. But maybe that was a different problem, since, looking at the
    code, I think I used a prompter that rejected all password prompts, which
    is sort of the opposite problem from the problem you're having.

    --
    Russ Allbery (eagle@eyrie.org) <https://www.eyrie.org/~eagle/>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BuzzSaw Code@21:1/5 to Russ Allbery on Tue May 10 16:58:17 2022
    Copy: ghudson@mit.edu (Greg Hudson)
    Copy: kerberos@mit.edu

    On Tue, May 10, 2022 at 4:54 PM Russ Allbery <eagle@eyrie.org> wrote:

    Greg Hudson <ghudson@mit.edu> writes:

    The FAST negotiation is irrelevant, except insofar as it makes the
    design of FAST OTP possible. Client preauth modules implementing OTP mechanisms simply don't consider the Kerberos password to be the same as
    an OTP value, so they ask for the OTP value via the responder or
    prompter.

    Oh, I think this was the bit that I was missing. I was for some reason assuming that the Kerberos library itself understood that part of the
    thing passed in as a "password" was actually an OTP value and the other
    part was a password, but it sounds like I was wrong to think this, and instead the entire "password" is sent via RADIUS and it's the RADIUS
    server that takes it apart into an OTP value and an actual password?

    And therefore, because of that, the Kerberos library declines to send a password passed in as an argument to krb5_get_init_creds_password to the RADIUS server, and always forces a separate prompt, because it is really designed for the case where the password and OTP are separate and entered separately at two different prompts, the second (for the OTP) triggered by the preauth mechanism?


    But that prompt is a callback to the prompter routine in pam_krb5 passed in
    so I could bypass that prompt by just force feeding the "password" into the response structure right ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)