I filed an issue with the library but my sense is that this is not possible to fix there. Copying:
As far as I can tell, GoogleAuthenticator library doesn't prevent a replay attack.
For this to be relevant we have to assume that either the victim is using an insecure network or has malware on their computer - both of which are not ideal, but happen more often than we'd like.
Would it be possible for GoogleAuthenticator library itself to prevent a replay? My guess is that the library doesn't have any way to persist data so it can't really prevent this kind of attack, but maybe you have ideas on that.
If it's not possible to solve in the library, then I suggest adding a note to the README to encourage people who use the library to add a feature to their code to prevent replay.
So, this protection is likely to have to happen in the totp code in tfa_basic.
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | 2329867-tfa-basic-totp-replay-7.patch | 9.82 KB | coltrane |
| #6 | 2329867-tfa-basic-totp-replay-6.patch | 9.82 KB | coltrane |
| #4 | 2329867-tfa-basic-totp-replay-4.patch | 8.73 KB | coltrane |
| #2 | 2329867-tfa-basic-totp-replay.patch | 8.5 KB | coltrane |
Comments
Comment #1
lva commentedI posted part of a possible solution to the library maintainer at https://github.com/PHPGangsta/GoogleAuthenticator/issues/9
Instead of passing around only seeds, you should pass an array by reference. This array contains the seeds and the timeslice of last successful authentication. The array can then also contain other information like number of successful and failed authentications (which can then also be used to lock the token).
The tfa_basic module would have to modify the database table in which it stores the seeds so that it can handle the storage of this array. I recommend to serialize it and then to encrypt/encode it as you already do.
Furthermore, after calling the verifyCode function of the GoogleAuthenticator library, the tfa_basic module should save the array back to the database since it will be changed (hence the passing by reference).
Comment #2
coltraneFeature + test.
New table stores salted hash of accepted TOTP codes to prevent replay attack. TOTP plugin rejects codes that are stored. Stored codes are cleared on cron after 1 day, variable controlled.
I think this is a candidate feature for moving to TFA module itself, but will test here first.
Comment #3
wim leers"wait for application" -> "wait for the application"
Nice & simple :)
Comment #4
coltraneThanks for review @Wim Leers!
Updated message and used else conditional so as to have a single return statement.
Comment #5
gregglesI think an index on the time_accepted would help the cron runs go a good bit faster.
+1 from me, with or without that new index.
Comment #6
coltraneAdd index in time_accepted and also expanded test to confirm cron deletes accepted codes.
Comment #7
coltraneA reroll to cleanly apply since tfa_basic_update_7002() conflicted.
Comment #9
coltraneCommitted