I develop a sort of social network for mobile and desktop browser with a REST API.

I can't ask to users to buy a U2F key or any hardware (but I could propose to support it if they have, since Chrome/Firefox support it natively now).

I don't want to ask a password because the majority of users uses the same password on multiples websites. So it's easy to hack a weak website, that may be store in clear text the password, or hashed but not salted and to use rainbow tables to obtain the password in clear.

I need to prove identity of the user when he lost credentials, but I don't want the classic OTP link by email/sms because this open a vector of attacks (eg: I give 5min my mobile to my wife, she's not an hacker/geek but she easily have the idea to click « I forgot my password », go on Mail/SMS application (iOS/Android don't ask password) and click on the OTP link to reset my password and be connected on my account. )

I don't want to ask on registration some personnal questions/answers, because your wife/family/friends could generaly answer, because it's a privacy leak, and because the user don't always remember the exact words/syntax used.

I search a user-friendly way to resist to theses attacks. ( So please, STOP to tell me to use a scheme exposed to theses attacks! ).

I have a scheme suggestion, most experts here doesn't like to think about new scheme, but all existing schemes I known don't solve theses attacks :(

My question is simple: is my scheme is less secure than the 99% of websites exposed to theses attacks and if the answer is yes, please tell me how you could attack my scheme ?

My scheme idea: https://medium.com/@lakano/an-idea-to-have-a-user-friendly-safe-authentification-3766af611560

closed as unclear what you're asking by Polynomial, ThoriumBR, Steve, Robert Mennell, Matthew Sep 20 '17 at 20:18

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

up vote 2 down vote accepted

You've got a lot of work ahead of you if you're building your system from scratch and trying to make it as good as industry-established (and often easy-to-use) methods. You're taking on the ambitious feat of trying to replace three things at once by replacing passwords with passcodes, replacing secure cookies and other methods of device identification with your pre-shared token scheme, and replacing preshared written-down codes or TOTP device verifification with your recovery file. Trying to do all this yourself opens plenty of security concerns that you may not even be aware of, like how to hash the passcode, prevent other systems from phishing your system, how to mitigate brute force and DoS, or other specific issues like XSS and SQL injection.

Edit: Also, since you keep suggesting "fixes" like increasing the number of tokens and adding encryption, keep in mind that adding complexity won't solve most of the root problems here, especially if you don't understand what the root problem. There are industry-standard ways of solving these problems that you're avoiding here and until you understand those and their rationale in detail any "improvement" to your system will likely still not be secure.

Some problems to consider, which are already solved by established methods like Gmail with Yubikey, or Google Authenticator:

  • Why do you assume account recovery over email is unacceptable but storing a recovery file on the cloud is acceptable? In practice the recovery file may be obvious so this doesn't seem like a valid assumption.

  • Why do you assume a password is unfriendly but remembering a sufficiently long passcode of random digits isn't? Even an eight-digit passcode is relatively weak by modern standards. If you're worried about password reuse, force users to have a sufficiently strong password so that their password elsewhere can't be cracked easily, or assign a password during account set-up using a friendly scheme like "correct horse battery staple" (or maybe, if you have to, request regular password changes).

  • Good security systems prevent replay attacks by using things like secure cookies that expire, session id's, secure hardware, or timestamps. It doesn't matter much if your device authentication only repeats every "one or two months" if you have no way of preventing attacks outside that time frame.

  • Your method of CRC'ing the file, then hashing it with a salt sent by the server, seems like a weak implementation that could have used more established methods like pre-shared keys, message signatures, or challenge-response authentication. I'm not sure why you're hashing the value on the client side when you're already assuming SSL will prevent MITM attacks (it won't always). The attacker can just send the hashed version. Having a salt won't protect against replay attacks if it's always the same for each user.

  • Your device authentication with a stack of ID's stored on the machine is not secure since I can easily steal the token if I have file access on your machine. Normally access to an authenticated device is game over for the second factor in 2FA, but you seem to care about this vector so I'll mention it anyways. (Note that Google Authenticator has the same issue, but other solutions like Yubikey don't).

  • What if I set up a fake copy of your website and ask for credentials? There are normally protections in the browser and web service to prevent or mitigate this but I don't see those mentioned here.

  • What's to prevent the user from picking a laughably insecure passcode like 1234? Strong modern password services either require high password length or complexity, denying weak passwords, strong protections against brute force, or all the above.

  • You seem to think that randomizing things like the length of the passcode, the location of the recovery file, or the number of tokens creates a significant defense. This is security through obscurity and is not recommended at all. A similar problem exists for your scheme to combine two tokens from a stack instead of one token. Real security is done by completely blocking avenues of attack or making them trillions of times more difficult, not just a few times more difficult. You don't really make a building more secure by hiding the entrance.

  • As others have mentioned, you need to balance brute-force prevention with denial-of-service prevention. Just blocking a user after two tries makes it easy to log out or disable recovery options like recovery files and logging in from new IP addresses. Any feature of your software that can be trivially locked up by an attacker tripping brute-force detection is a failed feature. You need to use CAPTCHA, throttling, proof of work, etc. to stop brute force, not draconian lock-outs or log-outs.

  • How are you going to handle all devices being lost? This is not an unusual situation and it's happened to me. For example, GMail asks you for printed-out codes or account details like date of account creation. It's not just as simple as checking their backup email. Asking users to back up their recovery file online is not an acceptable solution because you're basically asking someone else to provide the "external service" you're trying to avoid.

  • Having the user select a file and protect it afterwards is not very user-friendly. You're basically asking the user to hide their recovery key to make up for your security deficiencies, and most users won't hide it well. If you think every user will select a file completely randomly from thousands of similar files, then back it up to the cloud in a nondescript location and religiously protect it from deletion and modification, just in case they need a backup authentication method, you're ridiculously overestimating the amount of work they'll do for you.

If you want to know a single avenue of attack that I'd use, first I'd spoof random IP addresses like proxies and have their IP addresses deauthorized for file backup. It's unclear whether you check device authorization or passcode first, but in the former case I'd enter hundreds of emails into your form to spam users with authentication requests, and in the later case I'd block tens of thousands of IP addresses by trying to enter passcodes on them. Then after this fun, I'd start the real attack. I'd drop into an internet cafe or otherwise stage a MITM attack (by hoping a user clicks through a certificate error like they usually do, using DNS poisoning, or exploiting an SSL vulnerability), then wait several months if I have to and launch a replay on the device ID/token and passcode since you don't have good protections against brute force or replay attacks.

Edit: revised a lot above, see for details.

No, this is a steaming mess. In fact it would be a misnomer to even call this 2FA. Really what you've done is eliminate one of the factors and this is closer to side channel authentication than two factor authentication.

In addition to not having a proper second factor you've created a system with unnecessary complexities and a non-standard interface. This will bite you in two different ways. First, your users will not know how to use the system. Secondly, you won't know how to program it.

Because it's non-standard your users will be perpetually confused. They will make mistakes and compromise their own security simply because they are unfamiliar with the system.

Also because it's non-standard you will make mistakes. The burden of implementing each layer of security will be on you and because there are not well established patterns using this concept you will inevitably compromise the system. This is analogous to rolling your own crypto. Even at the conceptual stage you suggested the wrong technology using a file integrity checksum that is not collision resistant. But the issue here it goes deeper than that. Even if you were to correct that and use the proper hash type, you're exposing all sorts of attack surfaces that your don't know about and that don't have standard mitigations built into other software (for example browsers that have extra tricks to protect users from password phishing won't know how to protect them from this use of a file API—it wasn't designed with this use in mind).

Don't go down this road. For the sake of your users stick to more established patterns and normal 2FA.

  • 2
    Correct, in essence this is building your own software token implementation. What could go wrong with a checksum, not even a hash, of 32 bits? – hspaans Sep 20 '17 at 6:49
  • 4
    @lakano Properly implemented 2FA would not allow authentication with just a magic link from one email. Admittedly lots of systems advertise 2FA without really adding the security it offers, but If you don't understand proper 2FA you are in no position to provide an alternative. You haven't given enough detail in your concept to prove which vectors you would be opening, but it sounds like even if we tried you'd just try to talk yourself around them. What I'm offering is not a code review, it's a review of the overall concept—and I'm suggesting it's not a good read for you to go down. – Caleb Sep 20 '17 at 8:17
  • 5
    @lakano I stand by my answer. All your edits do is clarify that you are trying to re-invent a wheel and don't actually know what you are doing. This is a bad idea fro the same two general reasons I list here. You are trying to solve the problems of single factor authentication — I am not saying to do what 99% of sites do, I am suggesting you spend your time and energy learning and implementing established 2FA best practices. Good 2FA using existing mechanisms like OTP generator apps or hardware keys will protect your users better than your home-grown concept. – Caleb Sep 20 '17 at 10:26
  • 3
    @lakano Account recovery is generally one of the weakest links in authentication, you can either live with that or you can live with the fact that you're going to end up with some users unable to recover their accounts. I'd suggest looking into FIDO U2F, as this actually prevents phishing and proxy attacks, and iirc it's still secure in the event of database compromise. Your scheme prevents none of these things. – AndrolGenhald Sep 20 '17 at 14:29
  • 2
    @lakano If you don't want to rely on your users buying a hardware token at the very least look into an existing TOTP system instead of trying to build your own system. – AndrolGenhald Sep 20 '17 at 14:33

There are so many issues with this, but given that your main question is about 2FA and you are asking what the attack is...

2FA is intended to mitigate a compromise of one of the authenticators. Using 'something you have' in addition to 'something you know' ensures that if an attacker has access to the data flow between user and authentication system i.e. they can observe the 'something you know', then the attacker will need to do something further to gain access, the hope being their attack will fail at this stage.

In your scenario an attacker with access to the data flow will be able to observe the password (something you know) but also details of the file selected for 'authorizing a device', therefore to attack the system all they need to do is to create another file that has the same characteristics and they can authorize their malicious device and pretend to be an authorised user.

If the attacker has access to the data flow they can also amend the data so that it appears the data is coming from a different device and force your file CRC user prompt check thing and capture the details.

The file CRC step does not introduce an additional factor that requires a different type of attack, therefore it adds little value beyond some additional complication.

I think your fundamental misunderstanding is what qualifies as 'something you have' I do not like quoting Wikipedia, but to be consistent with your out of context quote about what 2FA is...

Possession factors ("something only the user has") have been used for authentication for centuries, in the form of a key to a lock. The basic principle is that the key embodies a secret which is shared between the lock and the key, and the same principle underlies possession factor authentication in computer systems.

Your premise is that a file is something that one of your users has, but for it to be an effective secret it relies upon only the user knowing which file it is, therefore it is another 'something you know'.

Would you lock a safe with a key and hang it up with a thousand other keys and think 'yeah that'll fix them darn thieves, I am the only that knows which hook the correct key is on'?

Generally speaking something you have factors should not be easy to copy (so that there is some sort of assurance that if the user has it no one else can) and has some way of demonstrating currency, this helps to prevent replay attacks, for example if someone can see something being entered, there are lots of other things, but hopefully you get the point. Go read up in more detail about desirable properties etc.

What you have described is not 2FA.

As an aside it is entirely unclear how you are confirming a device is an authorised device, I suspect there will be simple attacks on whatever you have for that as well.

  • You forget something. The attacker need an authorized device, so even if he could hack the HTTPS communication to listen the digits code, it's not enough. And if we said the CRC32 hashes are only sent to the server on the registration time, the attacker shouldn't sniff the CRC32 later. Excepted if you think the attacker sniff the registration process but it's the same problem for any websites... – lakano Sep 20 '17 at 10:57
  • 3
    Your question was about 2FA, now you are moving the goalposts. But nonetheless man in the browser attack etc...I'll not perpetuate this any further. – R15 Sep 20 '17 at 11:04
  • I don't move the goalpost, the goalpost is to check if my 2FA system is good... an attacker need something the user have (an authorized device, or for the rescue, a previously selected file on his harddrive) and something he known (digits code, or for the rescue, which file on his harddrive was used on registration). – lakano Sep 20 '17 at 11:07
  • BTW, 2FA definition (on Wikipedia) is « Two-factor authentication (also known as 2FA) is a method of confirming a user's claimed identity by utilizing a combination of two different components. Two-factor authentication is a type of multi-factor authentication. » – lakano Sep 20 '17 at 11:17
  • 2
    @lakano The system you describe is not even a second factor, it is just an obscure version of two things you know. – Caleb Sep 20 '17 at 16:46

After reading the question, and the medium post it is pretty clear that the attack vector and/or the full security theater being operated in is not fully understood.

Taken from thousands of questions all over security:

Don't roll your own security scheme!

There's MANY reasons for this, the least of which is that you would need to pour time to develop, resources to test, and external objective assessment of your scheme to make sure it's safe before deploying it. This takes a LOT of money.

The biggest reason you don't want to your own scheme is that if you roll this and release it and it's unsafe you've done a MASSIVE disservice to yourself and your users. Worse yet if you propagate it you've done a massive disservice to the world.

You need to take a step back and really evaluate what you're trying to do in an objective manner and look up some best practices. Especially since your question can be boiled down into much smaller, already asked questions:

How do I correctly implement MFA in a user friendly and safe way?

That question was answered years ago: Time Based Codes which have been standardized and widely adopted( asker has stated in comments that Hardware Keys are a no go).

How do I securely let a user recover their account?

That question was answered years ago: Secure third party channels and One Time Use passwords because really there just is no other way.

How do I keep users safe from themselves?

This question is a known quantity: You can't. Ever. A user is only as secure as the user keeps themselves

The bigger problem is that it will never matter if the user themselves is compromised.

  • Please, tell me which website use a good MFA with recover solution. I'm pretty sure there is multiple attacks possibles to hack the account. Of course, we can't ask to user to buy hardware like YubiKey... – lakano Sep 20 '17 at 18:19
  • And tell me please, how you could hack my scheme? – lakano Sep 20 '17 at 18:20
  • 1
    Note that when multi-factor authentication is used, secure account reset services will often use other channels besides one-time-use passwords. GMail, for example, will ask questions like the date the account was created, and Duo-based logins will let you print out a set of preshared passcodes for recovery. Github let's you pre-configure your Facebook account so you can use Facebook for recovery. Contrary to the asker's expectation, account recovery isn't just about sending the user an email. – Cody P Sep 21 '17 at 6:17

I am going to answer this question by raising rhetorical questions and using them to reason about your system.

How are you planning on determining whether a request originated from a 'authorised device' (in other words, how does an 'authorised device' prove to your REST API that it is indeed an authorised device)? Are you sending a cookie along with every request? Do you have a TPM that you're doing challenge-response with? What happens if a user makes a backup of his device and restores it on a new device? Is the new device automatically 'authorised' too?

As I understand it, when you're doing account recovery, you're not sending the 'rescue file' to the server but instead sending the CRC32. (Why does it specifically have to be a CRC32? It seems like an odd choice since it's a file-integrity checksumming algorithm rather than a hashing algorithm per se. Why not CRC8? Why not MD5? Why not SHA256?) Why store the rescue file at all? Why not just store the CRC32 itself? Why not just have the device send the CRC32 along with every request?

In fact, why not just have the user memorise the CRC32 along with his 'digits code'? (I'm also not sure why you decided to limit your 'digits code' to 4-16 long (and only to numbers) since it reduces the entropy significantly.)

Hang on, if your system requires the user to enter in his 'digits code' and send the CRC32 to log in, doesn't this essentially mean that the combination of the static CRC32 value and the digits code is a password?

I'm not convinced you have a second factor at all here.

Your rate limiting of locking users out after 2 failed attempts daily also opens your system up to a DoS vulnerability. I can lock any user out of the system just by repeatedly sending failed logins as that user.

I don't see how any of your proposed solutions prevents any of the attacks you've mentioned. I'm going to echo the sentiments of the other answers that you're making things unnecessarily complex for no or negative gain in security and usability.

The standard way of achieving the level of security you want is:

  • 2nd factor is required for anything sensitive (i.e. account changes or logins).
  • 2nd factor is something like a TOTP generator or perhaps a U2F device that produces tokens that can only be used once. In addition, a list of one-time-use recovery codes that the user writes down on a piece of paper in case they lose their primary method of 2FA.
  • Account recovery is not possible without a 2nd factor (i.e. you still get a link to reset your password to your email but you still must have your second factor to actually change your password).

I know at least Heroku, GitHub and Google does it this way. It's a standard way of doing things, you're less likely to make mistakes, your users will understand how to use it. You get free brute-force protection too since the 2FA tokens are one-time use.

tl;dr: Your solution is overly complex, adds little to negative security and there are tried-and-tested standard ways of achieving what you want.

  • Firstly, thanks @tangrs for your time and answer. I currently writing a long post on Medium to explain with most words / graphics what I'm trying to explain with few words here. I'll update the post with the link in few hours. To quickly answer to your questions: – lakano Sep 20 '17 at 15:51
  • 1
    Right, so you're essentially sending a cookie with every request to identify the device. I don't see how this prevents a DoS attack though. If the user has lost his device, he'll need to send his 'digits code' and CRC32 of the 'rescue file' to regain access right? What stops me from sending wrong login info to your account recovery page to lock people out? – tangrs Sep 20 '17 at 16:04
  • 2
    Wait, but how would account recovery work then? So if a user loses his device, you're saying he needs to authorise his new device from the device he's just lost to regain access? – tangrs Sep 20 '17 at 16:16
  • 2
    You're solving brute-forcing but you're still not solving the DoS issue here. Say you've lost all your authorised devices and now you need to get back in but I'm spamming the login with fake info and getting both of us locked out. – tangrs Sep 20 '17 at 16:30
  • 3
    You're going pretty damn deep into this rabbit hole of yours - playing whack-a-mole with vulnerabilities. I don't see how your system offers any more security than the vastly simpler and more widely accepted and used method I mentioned in my answer. – tangrs Sep 20 '17 at 16:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.