- From: Aditya Mitra via GitHub <sysbot+gh@w3.org>
- Date: Sat, 16 Sep 2023 13:48:54 +0000
- To: public-webauthn@w3.org
Yeah sure. It was because I used multiple screenshots so I had uploaded it in pdf format. Web authentication, in the end is a JavaScript API and still follows all the rules of JavaScript. This includes features like Function Overriding. This implies, if we push a custom implementation of the navigator.credentials.get() as a XSS (Cross Site Scripting), it can override the native implementation of the same function and the WebAuthn calls will not function as it is supposed to. This can be verified by simply entering the following code into the console window before making a WebAuthn call: ``` class cred { static get(options) { console.log("Get Called"); } } class navigator { } navigator.credentials=cred; ```  The adversarial actor can perform a Self-XSS on his own system to modify how WebAuthn works for him. He can then capture the ‘options’ and send the same to the legitimate user to sign. One major issue that might arise here is that even if the client is on a phished webpage, the RP ID verification fails. This is because the challenge arises from the legitimate RP Server and must be signed by the keys enrolled against that RP Server only. This is overcome by not directing the legitimate user to his web browser. A trojan on the legitimate user’s system might be able to access the Authenticator while impersonating the RP Server without verification. The trojan uses the python implementation of the FIDO2 library. This choice can be justified with a better look at the client.py file in the FIDO2 library.  The _verify_rp_id() function cryptographically verifies the RP ID against the origin from which the function is called. However, the origin can be specified as a string for the library, as seen in the __init__ constructor. Hence, the attack model might be, the adversarial actor runs a Self-XSS to extract the ‘options’ sent by the RP Server. These options and the origin are now sent to Trojan running on the user’s system. The trojan invokes the authenticator and might require user verification with Fingerprint or a Pin. The legitimate user is assumed to touch his fingerprint sensor or enter the pin as a part of a sophisticated social engineering attack. The signed challenge, in the form of the PublicKeyCredential is sent back to the adversarial actor, who then returns the same to the custom implementation of navigator.credentials.get(). It is then returned to the RP Server from the system of the adversarial actor. Thus, the RP Server authenticates the adversarial actor as a legitimate user. It is to be noted that the custom implementation of navigator.credentials.get() needs to convert the ArrayBuffers in the ‘options’ to arrays and then to JSON so that it can be sent to the applications running on the machine of the adversarial actor. It also needs to encode the response back to the desired formats. Attack scenario For the attack scenario, the adversarial actor has a cloud server that is used only to exchange the data between the system of the adversarial actor and the trojan. Any other messaging client could also be used instead of this cloud server. The adversarial actor further runs an application on his machine. The application first copies the script to be injected into the clipboard so that the adversarial actor can paste it in his browser console. The application then captures the ‘options’ from the malicious navigator.credentials.get() implementation and encodes it into Base64 and then sends it to the cloud server. The trojan running on the system of the legitimate user requests this Base64 data from the cloud server. It decodes the Base64 into proper WebAuthn format, performs the challenge signing and then encodes the results back into Base64 and sends it back to the cloud server. The cloud server returns the response back to the adversarial actor’s system. The application decodes the Base64 and returns it to the malicious implementation of navigator.credentials.get(). The implementation then decodes it back to ArrayBuffers and returns it to the RP Server. The codes used for the following is available here: • Cloud side: o [https://adityamitra5102.github.io/fidovulntest/cloud/flaskapp.py](https://adityamitra5102.github.io/fidovulntest/cloud/flaskapp.py) This application is served by Apache Webserver in the cloud. o [https://adityamitra5102.github.io/fidovulntest/cloud/requirements.txt](https://adityamitra5102.github.io/fidovulntest/cloud/requirements.txt) This is the dependencies for the application. • Adversarial actor side: o [https://adityamitra5102.github.io/fidovulntest/attacker/flaskapp.py](https://adityamitra5102.github.io/fidovulntest/attacker/flaskapp.py) This application runs on the machine of adversarial actor so that the malicious implementation can communicate to localhost:5000. o [https://adityamitra5102.github.io/fidovulntest/attacker/inject.js](https://adityamitra5102.github.io/fidovulntest/attacker/inject.js) This is the Self-XSS code to be pasted in the browser console before WebAuthn call. o [https://adityamitra5102.github.io/fidovulntest/attacker/requirements.txt](https://adityamitra5102.github.io/fidovulntest/attacker/requirements.txt) This is the dependencies for the adversarial side application. • Trojan o [https://adityamitra5102.github.io/fidovulntest/malware/malware.py](https://adityamitra5102.github.io/fidovulntest/malware/malware.py) This is the basic implementation of the Trojan. o [https://adityamitra5102.github.io/fidovulntest/malware/requirements.txt](https://adityamitra5102.github.io/fidovulntest/malware/requirements.txt) This is the dependencies for the implementation of the Trojan. The repository containing the code is not made public for obvious reasons. But the codes can be accessed from the above links. The attack scenario was tested, and the adversarial actor was able to take over the Google account of the legitimate user in the process. The Google account was secured with Passkeys with Windows Hello.  Full video of the case study is available here (unlisted video): [https://youtu.be/Lh45VzZqQ60](https://youtu.be/Lh45VzZqQ60) -- GitHub Notification of comment by AdityaMitra5102 Please view or discuss this issue at https://github.com/w3c/webauthn/issues/1965#issuecomment-1722234540 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Saturday, 16 September 2023 13:48:57 UTC