Hi everyone, currently working on migrating in-hou...
# general
d
Hi everyone, currently working on migrating in-house auth to kratos. For privacy reasons we need to hide whether or not a particular email address exists. We are looking at using
password
,
code
and
oidc
methods. So far it seems
password
registration and
code
login both reveal whether or not an email address exists. Registration I can work around using the “invite” pseudo-flow. But when you attempt a
code
login for an email that does not exist you get “This account does not exist or has not setup sign in with code.” Is there a way to turn off this error message? This seems like a clear vector for email enumeration, am I misunderstanding something?
I’ve tried hooks, but there does not seem to be a hook that runs after the user has entered their email but still gets executed if the email does not exist. So it doesn’t seem possible to intercept this error. One option is to run a proxy in front of kratos’ public API, but a big advantage of kratos (for me) is to provide a simple, public api that different services can talk to.
d
I believe the wording of the message is deliberately ambiguous - either the email doesn’t not exist OR maybe it does but hasn’t setup code - for this reason.
d
Thanks for the reply. (Unless I am mistaken)
code
is enabled globally, not individually. At least I was just now able to set up an account using username+password and then confirm the account exists by getting the “An email containing a code has been sent to the email address you provided. If you have not received an email, check the spelling of the address and retry the login.” message. Because the two messages are different, anyone familiar with kratos can distinguish them. I feel I must be misunderstanding something here.
Updated to kratos 1.3.1, tried
security.account_enumeration.mitigate: true
, no luck. Also tried in combination with
selfservice.flows.login.style: identifier_first
which (helpfully) lets you enter your email without telling you it doesn’t exist, but then still displays the leaky error message when you select
code
.
e
Copy code
An email containing a code has been sent to the email address you provided. If you have not received an email, check the spelling of the address and retry the login
I read this as not leaking the email address, but rather a message to tell the user that an email has been sent to the address entered. In theory you could enumerate the userid if your invalid email address never gets a code, but otherwise you would have to compromise every legit email system to get the code to know if it is a legit user.
d
Thanks for the reply. The expected behaviour (in my opinion) is that you always get that message. In that case (as you say) an attacker has no way of telling whether or not the email actually got sent unless they compromise the email system. But this is not the actual behaviour. If the email does exist you get
Copy code
An email containing a code has been sent to the email address you provided. If you have not received an email, check the spelling of the address and retry the login.
If the email does not exist you get
Copy code
This account does not exist or has not setup sign in with code.
So anyone familiar with kratos can determine whether or not an email address exists by initiating a
code
login and seeing which message they get.
d
you could override the translation strings to just use whatever error message you like
d
Now there’s an idea! Completely didn’t think about translation strings, since all of our users are english-speaking. Although having thought about it a second I think it doesn’t work; the
message
is actually an object, it also includes a
code
and a
type
. Even if the
text
matches, the messages will have different
id
and
type
. Good idea though, I will investigate it a bit more
d
ah yeah it depends on whether you are rendering Kratos’s forms server side or in the client
d
I’m happy to SSR; most of our services are nextjs, so moving on and off SSR is easy. But I was hoping to expose the kratos self-service API directly to the internet (via caddy for https). In this case an attacker can run a
code
login flow themselves and access the true error messages. I can run a proxy that restricts access to the self-service API, e.g. only exposing
/sessions/whoami
to the public internet … but this is a decent amount of complexity to add, just to hide one error message.
c
This is a valid concern, in one of our security review, this is pointed as email enumeration, I wonder why nobody paid attention to this. @high-optician-2097 @magnificent-energy-493 @enough-yak-81379
m
Hey @colossal-airline-19852 how are you using Ory? Can you share some background on the use case and what your requirements around enumeration are? You can also report this in our bug bounty program if you think it is a vulnerability.