• Avoiding Pre-Auth/Auth Principal State Disclosure

    From Eric Hattemer@21:1/5 to All on Tue Jun 30 22:53:44 2020
    If you run a client like kinit and ask for a principal with
    REQUIRES_PRE_AUTH and a disabled/pw_expired/locked-out state, or request
    a principal that doesn't exist, you aren't asked for a password and get
    an immediate response with the status of the account.  Is there a way to
    avoid this behavior?  People have created hacking toolkits that try
    every possible username to download the list of usernames in the
    database and their state.

    I know pre-auth is a special case where you'd need to provide a
    plausible challenge for non-existent accounts.  But is there maybe a
    setting to treat unknown principals as if they had pre-auth disabled,
    request a password, and just send back invalid password / encryption
    failed no matter what?

    We were trying to implement an authentication proxy module that uses
    Kerberos, and we wanted to only disclose an account was disabled if the
    user typed in the correct password.  But the only case we could make
    work was if the account was expired (different from pw_expired).


    --
    Eric Hattemer
    Engineer
    Identity and Access Management

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Hecker@21:1/5 to Eric Hattemer on Tue Jun 30 23:55:52 2020
    Copy: kerberos@mit.edu (kerberos@mit.edu)

    There are actually a bunch of places that leak information about valid
    princs, I wonder if there’s a todo item to clean those up at some point? I can’t remember the one or two I found since it was a while ago but I posted it to the list as well.

    Chris


    On Tue, Jun 30, 2020 at 23:01 Eric Hattemer <ehatteme@usc.edu> wrote:

    If you run a client like kinit and ask for a principal with
    REQUIRES_PRE_AUTH and a disabled/pw_expired/locked-out state, or request
    a principal that doesn't exist, you aren't asked for a password and get
    an immediate response with the status of the account. Is there a way to avoid this behavior? People have created hacking toolkits that try
    every possible username to download the list of usernames in the
    database and their state.

    I know pre-auth is a special case where you'd need to provide a
    plausible challenge for non-existent accounts. But is there maybe a
    setting to treat unknown principals as if they had pre-auth disabled,
    request a password, and just send back invalid password / encryption
    failed no matter what?

    We were trying to implement an authentication proxy module that uses Kerberos, and we wanted to only disclose an account was disabled if the
    user typed in the correct password. But the only case we could make
    work was if the account was expired (different from pw_expired).


    --
    Eric Hattemer
    Engineer
    Identity and Access Management

    ________________________________________________
    Kerberos mailing list Kerberos@mit.edu https://mailman.mit.edu/mailman/listinfo/kerberos


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robbie Harwood@21:1/5 to Chris Hecker on Wed Jul 1 14:24:52 2020
    To: ehatteme@usc.edu (Eric Hattemer)
    Copy: kerberos@mit.edu (kerberos@mit.edu)

    Chris Hecker <checker@d6.com> writes:

    On Tue, Jun 30, 2020 at 23:01 Eric Hattemer <ehatteme@usc.edu> wrote:

    If you run a client like kinit and ask for a principal with
    REQUIRES_PRE_AUTH and a disabled/pw_expired/locked-out state, or
    request a principal that doesn't exist, you aren't asked for a
    password and get an immediate response with the status of the
    account. Is there a way to avoid this behavior? People have created
    hacking toolkits that try every possible username to download the
    list of usernames in the database and their state.

    I know pre-auth is a special case where you'd need to provide a
    plausible challenge for non-existent accounts. But is there maybe a
    setting to treat unknown principals as if they had pre-auth disabled,
    request a password, and just send back invalid password / encryption
    failed no matter what?

    We were trying to implement an authentication proxy module that uses
    Kerberos, and we wanted to only disclose an account was disabled if
    the user typed in the correct password. But the only case we could
    make work was if the account was expired (different from pw_expired).

    There are actually a bunch of places that leak information about valid princs, I wonder if there’s a todo item to clean those up at some
    point? I can’t remember the one or two I found since it was a while
    ago but I posted it to the list as well.

    In my opinion, it's not generally a good idea to consider usernames
    private information. Typically they're predictable and should pale in comparison to password strength anyway.

    I'd additionally suggest turning on preauth for all user principals.

    Thanks,
    --Robbie

    --=-=-Content-Type: application/pgp-signature; name="signature.asc"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEEA5qc6hnelQjDaHWqJTL5F2qVpEIFAl781PQACgkQJTL5F2qV pEKi+xAAwk943legfZsDxlQ2qprW+rrcXnu78DgvfxSoIzLmRA1Is+GbqE3981fI qWOt1xn0tsFzsSi1el06n2E9ouvyRH6ueQlx6u/y4FCfKallAAQxRdZ2Pj1PhDHo OU3FtHrdqD6J94OXm+4EF0unakbEIQ7VLg/aITZobzPrd+ZanUILjmoLgmExGr2e pOsumnvRf2nLbIg0hs62pUij+deBZmZRwwizN7mjveF8LE3QijXBmK6L+n/em4aH AAZ957obz9iwb1WHyKnPpm0VBOyfnkrfPeGst4BVAK7ULdeBMveFNyFp0qdEke1/ XL2jlkEKZqvE+L6GxxRKwU4d1yWrQX+i7dYt1VYAj4bHwsrlC3+O3j5BdG5G7KAr DOU24QHUv4+7KRXMdGV6juG0Z0L3t5W/a3kGjTt/dnD+KKfB+tUJCA6KkXoObLwK /s4LQ78rZb/RwFynBFJW6g1ABZfurZCB2U4S59EFh4t//uWmejXinw5bkqEZLCnw KH6n/DFBypeysY7nDzf6tHlzXRHoVG0uzdphLVrI6IFtEMakCE+c+b1fmrfbgXtA sQ+U5PzcezIPbqpcdxRrNH7kopuHV6hXYf3c8takzNqRg9JFIbTlURDBBPvKrezm cRJOYzmocVuWdMBnS3/hCLwFZHHlo2OEUYa/qQvT0rc0z1EGr+g=svdU
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Hecker@21:1/5 to Greg Hudson on Wed Jul 1 12:55:36 2020
    Copy: kerberos@mit.edu (kerberos@mit.edu)

    For example, if we treated single-component principals as users,
    anyone with a user/admin principal (or user/root, which has no status in
    the code but is a common convention for elevated access) would probably
    still be detectable by an attacker.

    Not sure I follow this, why wouldn’t they be treated like a normal princ if we had this obscurity feature? I remember assuming vague errors would fix
    this but then discovering it didn’t, which was surprising. I build my KDC myself so I wasn’t worried about that part, I just was surprised it wasn’t possible.

    Chris


    On Wed, Jul 1, 2020 at 12:39 Greg Hudson <ghudson@mit.edu> wrote:

    On 7/1/20 1:53 AM, Eric Hattemer wrote:
    I know pre-auth is a special case where you'd need to provide a
    plausible challenge for non-existent accounts. But is there maybe a setting to treat unknown principals as if they had pre-auth disabled, request a password, and just send back invalid password / encryption
    failed no matter what?

    We don't have a setting like that. The closest nod we have in the code
    to this desire is a "vague errors" setting for the KDC, which can only
    be turned on at compile time (or via ptrace, I guess) and causes the KDC
    to yield generic errors instead of useful ones. But that setting still allows an attacker to easily distinguish between "client principal
    requires preauth" and "client principal not found".

    Because the Kerberos principal namespace isn't formally divided between
    users and services, any obscurity feature would probably have some edge cases. For example, if we treated single-component principals as users, anyone with a user/admin principal (or user/root, which has no status in
    the code but is a common convention for elevated access) would probably
    still be detectable by an attacker. ________________________________________________
    Kerberos mailing list Kerberos@mit.edu https://mailman.mit.edu/mailman/listinfo/kerberos


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Hudson@21:1/5 to Eric Hattemer on Wed Jul 1 15:31:54 2020
    To: kerberos@mit.edu (kerberos@mit.edu)

    On 7/1/20 1:53 AM, Eric Hattemer wrote:
    I know pre-auth is a special case where you'd need to provide a
    plausible challenge for non-existent accounts.  But is there maybe a
    setting to treat unknown principals as if they had pre-auth disabled,
    request a password, and just send back invalid password / encryption
    failed no matter what?

    We don't have a setting like that. The closest nod we have in the code
    to this desire is a "vague errors" setting for the KDC, which can only
    be turned on at compile time (or via ptrace, I guess) and causes the KDC
    to yield generic errors instead of useful ones. But that setting still
    allows an attacker to easily distinguish between "client principal
    requires preauth" and "client principal not found".

    Because the Kerberos principal namespace isn't formally divided between
    users and services, any obscurity feature would probably have some edge
    cases. For example, if we treated single-component principals as users,
    anyone with a user/admin principal (or user/root, which has no status in
    the code but is a common convention for elevated access) would probably
    still be detectable by an attacker.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Hudson@21:1/5 to Chris Hecker on Thu Jul 2 13:45:54 2020
    Copy: kerberos@mit.edu (kerberos@mit.edu)

    On 7/1/20 3:55 PM, Chris Hecker wrote:
    For example, if we treated single-component principals as users,
    anyone with a user/admin principal (or user/root, which has no status in
    the code but is a common convention for elevated access) would probably
    still be detectable by an attacker.

    Not sure I follow this, why wouldn’t they be treated like a normal princ
    if we had this obscurity feature?

    The difficulty is in making a "normal princ" look identical to an actual
    normal princ.

    Let's say we added this obscurity setting to the KDC in the following
    naive way: if an unauthenticated AS request comes in and the client
    principal isn't found in the DB, we send PREAUTH_REQUIRED. If the
    request contains preauth (of a recognizable "real" preauth type) then we
    send PREAUTH_FAILED.

    Service principals can (and frequently do) authenticate as clients.
    Because they have random keys, they don't generally require preauth
    (partly because preauth would be a waste of round trips when the key is
    random, and partly because PREAUTH_REQUIRED has undesirable legacy
    semantics when applied to service principals). So without first
    authenticating as a legitimate client, the attacker can distinguish
    between a dummy response and a real response for a service principal.
    Perhaps we don't care about obscuring valid service principals, but if
    we do, we have to instead respond to AS requests for service-principal
    clients with a dummy ticket (of a size indistinguishable from a
    legitimate ticket) encrypted in a random key, instead of a
    PREAUTH_REQUIRED. And because there is no formal distinction between
    user principals and service principals, we can't trivially determine
    whether the client principal (if it existed) would be for a user or for
    a service.

    Additionally, in a PREAUTH_REQUIRED error, we have to send etype-info
    based on the request's enctype preference order and the client and
    server principals' supported enctypes. There's no client principal
    entry, so what enctypes do we assume are supported by the client?
    Perhaps we consult supported_enctypes. What if the administrator just
    recently began a transition from aes-sha1 to aes-sha2 enctypes? Most
    real principals will only have aes-sha1 keys, but supported_enctypes
    lists the aes-sha2 enctypes. In this situation it's easy to distinguish
    dummy responses from those for most real principals.

    The use of more advanced preauth mechanisms might further muddy things;
    for instance, principals intended to authenticate with PKINIT might have
    no keys, and therefore no etype-info. Perhaps we allow the
    administrator to create a template principal which has similar metadata
    to the majority of user principals, and use that for dummy responses.
    Now we're asking a lot from the administrator, and any kind of enctype
    or preauth transition would still create classes of users who are distinguishable from the template.

    We'd also have to consider whether to include TGS requests in the threat
    model. If the attacker is an insider or has compromised just one client account, they can try to build their valid principal list using TGS
    requests instead of AS requests. If we're just trying to obscure user principals this might not be too hard, assuming users have DISALLOW_SVR
    set. We'd have to send back S_PRINCIPAL_UNKNOWN instead of
    MUST_USE_USER2USER when the service principal has that flag.
    (Additional attention might need to be given to the user-to-user code
    path, as the attacker could try user-to-user with a bogus TGT.) If
    we're also trying to obscure service principals, the problem becomes
    much harder; we'd have to issue dummy service tickets for invalid
    services, again making sure the ticket size isn't distinguishable, and
    making the choice of ticket session key enctype indistinguishable from a
    normal service principal. Issuing dummy service tickets would create
    many problems for legitimate users, such as breaking dns_canonicalize_hostname=fallback.

    Finally, none of the above analysis considers side channels. If a dummy response takes a measurably different amount of time for the KDC to
    synthesize than a normal response, an attacker still might be able to distinguish valid from invalid principal names.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Hecker@21:1/5 to Greg Hudson on Thu Jul 2 14:05:14 2020
    Copy: kerberos@mit.edu (kerberos@mit.edu)

    Wow, thanks for taking the time for the detailed response! I will digest
    this and see if I still have questions.

    Chris


    On Thu, Jul 2, 2020 at 10:45 Greg Hudson <ghudson@mit.edu> wrote:

    On 7/1/20 3:55 PM, Chris Hecker wrote:
    For example, if we treated single-component principals as users,
    anyone with a user/admin principal (or user/root, which has no status in the code but is a common convention for elevated access) would probably still be detectable by an attacker.

    Not sure I follow this, why wouldn’t they be treated like a normal princ if we had this obscurity feature?

    The difficulty is in making a "normal princ" look identical to an actual normal princ.

    Let's say we added this obscurity setting to the KDC in the following
    naive way: if an unauthenticated AS request comes in and the client
    principal isn't found in the DB, we send PREAUTH_REQUIRED. If the
    request contains preauth (of a recognizable "real" preauth type) then we
    send PREAUTH_FAILED.

    Service principals can (and frequently do) authenticate as clients.
    Because they have random keys, they don't generally require preauth
    (partly because preauth would be a waste of round trips when the key is random, and partly because PREAUTH_REQUIRED has undesirable legacy
    semantics when applied to service principals). So without first authenticating as a legitimate client, the attacker can distinguish
    between a dummy response and a real response for a service principal.
    Perhaps we don't care about obscuring valid service principals, but if
    we do, we have to instead respond to AS requests for service-principal clients with a dummy ticket (of a size indistinguishable from a
    legitimate ticket) encrypted in a random key, instead of a
    PREAUTH_REQUIRED. And because there is no formal distinction between
    user principals and service principals, we can't trivially determine
    whether the client principal (if it existed) would be for a user or for
    a service.

    Additionally, in a PREAUTH_REQUIRED error, we have to send etype-info
    based on the request's enctype preference order and the client and
    server principals' supported enctypes. There's no client principal
    entry, so what enctypes do we assume are supported by the client?
    Perhaps we consult supported_enctypes. What if the administrator just recently began a transition from aes-sha1 to aes-sha2 enctypes? Most
    real principals will only have aes-sha1 keys, but supported_enctypes
    lists the aes-sha2 enctypes. In this situation it's easy to distinguish dummy responses from those for most real principals.

    The use of more advanced preauth mechanisms might further muddy things;
    for instance, principals intended to authenticate with PKINIT might have
    no keys, and therefore no etype-info. Perhaps we allow the
    administrator to create a template principal which has similar metadata
    to the majority of user principals, and use that for dummy responses.
    Now we're asking a lot from the administrator, and any kind of enctype
    or preauth transition would still create classes of users who are distinguishable from the template.

    We'd also have to consider whether to include TGS requests in the threat model. If the attacker is an insider or has compromised just one client account, they can try to build their valid principal list using TGS
    requests instead of AS requests. If we're just trying to obscure user principals this might not be too hard, assuming users have DISALLOW_SVR
    set. We'd have to send back S_PRINCIPAL_UNKNOWN instead of MUST_USE_USER2USER when the service principal has that flag.
    (Additional attention might need to be given to the user-to-user code
    path, as the attacker could try user-to-user with a bogus TGT.) If
    we're also trying to obscure service principals, the problem becomes
    much harder; we'd have to issue dummy service tickets for invalid
    services, again making sure the ticket size isn't distinguishable, and
    making the choice of ticket session key enctype indistinguishable from a normal service principal. Issuing dummy service tickets would create
    many problems for legitimate users, such as breaking dns_canonicalize_hostname=fallback.

    Finally, none of the above analysis considers side channels. If a dummy response takes a measurably different amount of time for the KDC to synthesize than a normal response, an attacker still might be able to distinguish valid from invalid principal names.


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