Support » Plugin: Password Reset with Code for WordPress REST API » Avoid brute force attack

  • Resolved alex0311

    (@alex0311)


    Hello,
    I have found that it’s very easy to hack a user account with this plugin.

    I explain.
    If we keep default setting, so 4 digit code and an expired time of 15 minutes (900seconds) and the fact that WordPress allow 50 request per seconds and per IP by default (even a poor server can handle more than 10 rest API requests per seconds) then in a case that attacker uses only one IP it would take approximately 200 seconds (less than 4 minutes) to reset a password.

    If you change digit number, it will approximately take :

    5 digits : 2000 seconds (33 minutes)
    6 digits : 200000 seconds (333 minutes -> 5,5hours)
    7 digits : 55 hours
    8 digits : 23 days
    9 digits : 231 days
    10 digits : 2314 days …

    2314 days could seem a lot but don’t forget here that’s we use only 1 IP.

    Hacker would more often use 10, 100 or 1000+ different IP

    Of course every 15 minutes (or more depends on the life of the code sent) you ask for a new code. (But if you still try the same range of number it won’t affect the chance to finding the password).

    So even with a 7 digits code it will be easy to hack a WordPress admin account in less than 6 minutes using only 10 different IP.

    Here are some suggestions to avoid this :

    Send a unique link after a password has been updated to enable the account.
    Send by email a new password instead of asking the user to add his own.
    Allow non-digit number to the code generated.
    If more than 10 bad code entered, block for 10 minutes or more, the API endpoint for the user. —> I think this is a great solution.

    Also, I think that it should have an option to block resetting passwords of an admin account with this method.

    What do you think of ?

    Kind regards

Viewing 8 replies - 1 through 8 (of 8 total)
  • Plugin Author dominic_ks

    (@dominic_ks)

    Hello,

    Thanks so much for sending this feedback and for the suggested solutions.

    Off the bat I think that adding letters as well as numbers to the code is an easy win, with uppercase and lowercase, as this should drop easily into the existing process and still be easy for users to enter.

    A filter to allow specifying the roles that you want to allow to use this method should also be an easy win.

    I also like the idea of locking accounts / blocking IPs after a number of bad attempts, so I’ll look into this one.

    I’m less in favour of sending a link to activate / reactivate an account as one of the main use cases for this plugin is when you’re not using the normal WordPress front end, so I’m not sure where this link would go, unless you could also specify your own URL, but still, more tricky to use for things like mobile apps if you don’t have deep links set up…

    Well, thanks again, I’ll be looking into these ASAP!

    Yes, locking and blocking is my favorite solution since it definitively prevents brute force attack.

    Plugin Author dominic_ks

    (@dominic_ks)

    OK, so I think the locking and blocking I am going to do but I need to just think through the process a little bit, specifically how can people unblock themselves if a legitimate user locks themselves out, but for some quick updates and to help protect the sites already using the plugin I’ve just released version 0.0.7 with the following changes, I’d be grateful if you wouldn’t mind giving it a test if you have any time available:

    • Added maximum allowed failed attempts to validate a code before automatically expiring it, default has been set to 3
    • Added filters to include letters and well as numbers in the reset code as well as allowing you to specify your own string
    • Added filters to allow the exclusion of certain roles from being able to reset their password, e.g. if you want to exclude Administrators

    Thanks,

    It looks good, I’ll try it tomorrow.
    For locking and unlocking account I think that you should save in MySQL the timestamp with email and check when a user ask a new code if timestamp is more than 10 min, else return an error.

    Thank you

    So I tried and there is a strange behavior :
    If you try an attempt after the code has expired, the plugin still try to check if the code has attempts left and if it is, it says that’s you have x attempts left and if not, says that you must request a new code.

    If you entered the correct code, then it says that’s the code had expired.

    Maybe it is the expected behavior ?

    Also, for the plugin description :

    FILTER THE CHARACTERS TO BE USED WHEN GENERATING A CODE, YOU CAN USE ANY STRING YOU WANT, DEFAULT IS 01234567890
    add_filter( ‘bdpwr_selection_string’ , function( $string ) {
    return ‘01234567890’;
    }, 10 , 4 );

    Default value should be 0123456789 instead of 01234567890, no ?

    Else, everything is working fine.

    Plugin Author dominic_ks

    (@dominic_ks)

    Thanks for that. Yes I have been back and forward on what order to execute the checks in, I may consider changing it later but for now I left it similar to before – i.e. previously it would continue to try and validate the code even if it were expired.

    NB. now that I think I have plugged the immediate need to do something here, I have created a few issues on GitHub to address the other points that I will pick up in my next round of development on this.

    Cheers,

    Plugin Author dominic_ks

    (@dominic_ks)

    Hi @alex0311,

    Did you have anything else you wanted to include in this thread or are you happy everything has been captured by the above GH issues?

    If so I’ll close this thread and continue the development activities on GitHub.

    Thanks,
    Dominic,

    alex0311

    (@alex0311)

    Hi, yes update has already added strong features to avoid a brute force attack.

    Thanks you.

    Closed.

Viewing 8 replies - 1 through 8 (of 8 total)
  • You must be logged in to reply to this topic.