Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Always prompting for OTP

14 views
Skip to first unread message

BuzzSaw Code

unread,
May 10, 2022, 11:48:45 AM5/10/22
to kerb...@mit.edu
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

Greg Hudson

unread,
May 10, 2022, 1:03:11 PM5/10/22
to BuzzSaw Code, kerb...@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.

BuzzSaw Code

unread,
May 10, 2022, 1:51:42 PM5/10/22
to Greg Hudson, kerb...@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.

Russ Allbery

unread,
May 10, 2022, 2:06:23 PM5/10/22
to BuzzSaw Code, Greg Hudson, kerb...@mit.edu
BuzzSaw Code <buzzsa...@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 (ea...@eyrie.org) <https://www.eyrie.org/~eagle/>

BuzzSaw Code

unread,
May 10, 2022, 2:41:17 PM5/10/22
to Russ Allbery, Greg Hudson, kerb...@mit.edu
On Tue, May 10, 2022 at 2:05 PM Russ Allbery <ea...@eyrie.org> wrote:

> BuzzSaw Code <buzzsa...@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.

Russ Allbery

unread,
May 10, 2022, 2:49:44 PM5/10/22
to BuzzSaw Code, Greg Hudson, kerb...@mit.edu
BuzzSaw Code <buzzsa...@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.

BuzzSaw Code

unread,
May 10, 2022, 2:58:30 PM5/10/22
to Russ Allbery, Greg Hudson, kerb...@mit.edu
On Tue, May 10, 2022 at 2:49 PM Russ Allbery <ea...@eyrie.org> wrote:

> BuzzSaw Code <buzzsa...@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.

Greg Hudson

unread,
May 10, 2022, 3:47:00 PM5/10/22
to Russ Allbery, BuzzSaw Code, kerb...@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.

Russ Allbery

unread,
May 10, 2022, 4:54:31 PM5/10/22
to Greg Hudson, BuzzSaw Code, kerb...@mit.edu
Greg Hudson <ghu...@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.

BuzzSaw Code

unread,
May 10, 2022, 4:58:58 PM5/10/22
to Russ Allbery, Greg Hudson, kerb...@mit.edu
On Tue, May 10, 2022 at 4:54 PM Russ Allbery <ea...@eyrie.org> wrote:

> Greg Hudson <ghu...@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 ?

Russ Allbery

unread,
May 10, 2022, 5:12:48 PM5/10/22
to BuzzSaw Code, Greg Hudson, kerb...@mit.edu
BuzzSaw Code <buzzsa...@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.
0 new messages