What about my idea?
To differentiate, we will call the channel that is being authenticated, as the “insecure” channel, and the channel the authenticator resides in, the “secure” channel.
After primary authentication has been done, show a random PIN code on-screen, on the “insecure” channel.
In the push request, send the same PIN code encrypted to the device., over the “secure” channel.
The Duo app requests the PIN code, and will “allow” only if the entered PIN code match the PIN-code in the push request. If the PIN codes mismatch, “disallow” the authentication request automatically. This binds the insecure channel hard to the secure channel.
Something like this (made the picture in paint, so you understand the idea):
And then when clicking “Send push request”, it will tell “Push request sent, Enter PIN code 3782 in your device” (where 3782 is a random code).
For those users that use the device PIN code as authentication to Duo Push, it could be wise to display a 4+[Device PIN length] passcode prompt, and say like “Push request sent, Enter PIN code 3782 followed by your device PIN in your device. (or enter PIN 3782 and authenticate with touch ID)”
So if a user has device PIN 9214, they would enter 37829214 as PIN, or enter 3782 (and leave 4 rings empty) and then touch finger.
To make this user-firendly, a touch ID icon or similiar, could be greyed out until at least 4 digits are entered, and then lights up to tell that you can either finish authentication by using touch ID, or continue entering digits to authenticate by device PIN. Of course touch ID should be made available even if a incorrect on-screen PIN is entered (but then, using touch ID would result in a “Disallow” action sent back).
And now to some more threat scenarios, not only the phone call one, which this are designed to prevent:
Imagine you are sitting at a public café. Or a internet café. Or a computer in the library. Or you are just sitting in the park with your computer connected to mobile 3G.
Regardless, you are sitting in a location so a adversiary could observe you, either by a binocular or oculary.
Now the adversiary does have access to the primary credentials. Since the adversiary could observe you, it means the adversiary could observe you beginning a login, and then do a “race attack” to get to send the push request first. Since the adversiary and the victim is roughtly on the same location, the details in the Duo Push application will not make you any smarter.
And since the user will think its his request, he will approve it, instead approving the adversiarys push request.
Imagine now the network is being eavesdropped by a attacker. Note that the attacker does NOT need to break SSL/TLS, and does NOT need to see the data. The only thing a adversiary needs to see, is the host or IP the user is contacting.
This attack could be mitiaged by using a VPN, but note that if Duo Push is used to establish that VPN, the connection to the VPN itself will reveal that the user are attempting a login. This means a VPN without Duo Push, preferably at a third party, needs to be used.
The attacker observes a DNS request or a TCP connection to the login service (like: login.acme.com).
Note that even if the connection is protected by SSL or TLS, the attacker can observe the host name by checking SNI information.
Now the attacker waits time T, where time T is a well tought out time to “race attack” the user, and then sends his own request using the user’s primary credentials. Note here that the same applies here, the attacker is close to the user, and the “verifying data” inside Duo push will not help.
The time T, which is the time the user uses to complete primary authentication, can be collected by allowing the user to do the authentication, but then denying the service, by for example flooding the user with packets, so the user reattempts the authentication. Now the attacker, by listening in on connections only, have recorded the time T, and can do a precise race attack.
Now the user will too think the authentication request belongs to himself and allow it.
Imagine my PIN idea was implemented in the above scenarios:
When the adversiary begins the “race attack”, the user will see on screen: PIN code “3992”, when the user initates HIS push request. He enters this into the push app. Since this push request was initiated for the same user, but by the adversiary a few seconds before, the PIN code expected will be “9187”, which the adversiary got on his screen. PIN code mismatch. Authentication “Disallowed”.