Insecure Paper FIDO2 on Chrome
Note: This gives Chrome your PEM data but allowed me to relogin on webauthn.io on a public computer without a physical key. From exhaustive rubber ducking with google search AI. Registering: 1. 3 dots -> More tools -> WebAuthn 2. Check Enable virtual authenticator environment 3. Click Add to create a new authenticator, optionally enable support for resident keys and user verification 3b: If the registration window is a popup and the registration flow may close the window, Sources -> Event listener breakpoints (right-hand pane) -> Load: check beforeunload and unload expand the webauthn credentials columns so they can be quickly copied out! 4. Register a device on the website => a row is added to the Credentials table. 5. Copy all the values from the table and export the PEM file (privat key) and copy the body text from it without the header and footer guards or linebreaks. This is your insecure, not-airgapped paper ID. 5b. if a breakpoint is raised resume execution to not time out, although the registration may stlil succeed if the flow times out Authenticating: 1. F12 / ctrl-shift-I / dev tools -> gear icon / settings -> Experiments -> enable Protocol Monitor 2. Reload dev tools and go to 3 dots -> More tools -> Protocol Monitor At the bottom raw CDP commands can be sent in JSON. 3. In the lower right dropdown next to the CDP command line, set the target to Main. 4. send: {"command":"WebAuthn.enable","parameters":{}} check the log and ensure no error is raised 5. send (removing any e-mail artefacts such as line breaks): {"command":"WebAuthn.addVirtualAuthenticator","parameters":{"options":{"protocol":"ctap2","transport":"usb","hasResidentKey":true,"hasUserVerification":true,"isUserVerified":true}}} check the log and ensure no error is raised 6. The last command produced an authenticator ID in its response. Copy this ID from the log. 7, Replace in the following command all the uppercase snakecase values with the copied values from before, and send it: {"command":"WebAuthn.addCredential","parameters":{"authenticatorId":"AUTHENTICATOR_ID","credential":{"credentialId":"CREDENTIAL_ID","isResidentCredential":true,"rpId":"CREDENTIAL_RP_ID","privateKey":"CREDENTIAL_PEM_FILE_BODY_STRING","userHandle":"CREDENTIAL_USER_HANDLE","signCount":1}}} check the log and ensure no error is raised 8. Authenticate on the website. It worked for me. On reuse only the authenticator ID need be changed from the last command.
> Note: This gives Chrome your PEM data but allowed me to relogin on
> webauthn.io on a public computer without a physical key. From
> exhaustive rubber ducking with google search AI.
>
> Registering:
0. F12 / ctrl-shift-I / dev tools on the hardware key registration page
> 1. 3 dots -> More tools -> WebAuthn
> 2. Check Enable virtual authenticator environment
> 3. Click Add to create a new authenticator, optionally enable support
> for resident keys and user verification
> 3b: If the registration window is a popup and the registration flow
> may close the window, Sources -> Event listener breakpoints
> (right-hand pane) -> Load: check beforeunload and unload
> expand the webauthn credentials columns so they can be quickly copied out!
> 4. Register a device on the website => a row is added to the Credentials table.
> 5. Copy all the values from the table and export the PEM file (privat
> key) and copy the body text from it without the header and footer
> guards or linebreaks. This is your insecure, not-airgapped paper ID.
> 5b. if a breakpoint is raised resume execution to not time out,
> although the registration may stlil succeed if the flow times out
>
> Authenticating:
> 1. F12 / ctrl-shift-I / dev tools -> gear icon / settings ->
> Experiments -> enable Protocol Monitor
> 2. Reload dev tools and go to 3 dots -> More tools -> Protocol Monitor
> At the bottom raw CDP commands can be sent in JSON.
>
> 3. In the lower right dropdown next to the CDP command line, set the
> target to Main.
>
> 4. send:
>
> {"command":"WebAuthn.enable","parameters":{}}
>
> check the log and ensure no error is raised
>
> 5. send (removing any e-mail artefacts such as line breaks):
>
> {"command":"WebAuthn.addVirtualAuthenticator","parameters":{"options":{"protocol":"ctap2","transport":"usb","hasResidentKey":true,"hasUserVerification":true,"isUserVerified":true}}}
>
> check the log and ensure no error is raised
>
> 6. The last command produced an authenticator ID in its response. Copy
> this ID from the log.
>
> 7, Replace in the following command all the uppercase snakecase values
> with the copied values from before, and send it:
>
> {"command":"WebAuthn.addCredential","parameters":{"authenticatorId":"AUTHENTICATOR_ID","credential":{"credentialId":"CREDENTIAL_ID","isResidentCredential":true,"rpId":"CREDENTIAL_RP_ID","privateKey":"CREDENTIAL_PEM_FILE_BODY_STRING","userHandle":"CREDENTIAL_USER_HANDLE","signCount":1}}}
>
> check the log and ensure no error is raised
>
> 8. Authenticate on the website. It worked for me.
>
> On reuse only the authenticator ID need be changed from the last command.
> > Note: This gives Chrome your PEM data but allowed me to relogin on
> > webauthn.io on a public computer without a physical key. From
> > exhaustive rubber ducking with google search AI.
> >
> > Registering:
> 0. F12 / ctrl-shift-I / dev tools on the hardware key registration page
> > 1. 3 dots -> More tools -> WebAuthn
> > 2. Check Enable virtual authenticator environment
> > 3. Click Add to create a new authenticator, optionally enable support
> > for resident keys and user verification
> > 3b: If the registration window is a popup and the registration flow
> > may close the window, Sources -> Event listener breakpoints
> > (right-hand pane) -> Load: check beforeunload and unload
> > expand the webauthn credentials columns so they can be quickly copied out!
> > 4. Register a device on the website => a row is added to the Credentials table.
> > 5. Copy all the values from the table and export the PEM file (privat
> > key) and copy the body text from it without the header and footer
> > guards or linebreaks. This is your insecure, not-airgapped paper ID.
> > 5b. if a breakpoint is raised resume execution to not time out,
> > although the registration may stlil succeed if the flow times out
> >
> > Authenticating:
> > 1. F12 / ctrl-shift-I / dev tools -> gear icon / settings ->
> > Experiments -> enable Protocol Monitor
> > 2. Reload dev tools and go to 3 dots -> More tools -> Protocol Monitor
> > At the bottom raw CDP commands can be sent in JSON.
> >
> > 3. In the lower right dropdown next to the CDP command line, set the
> > target to Main.
> >
> > 4. send:
> >
> > {"command":"WebAuthn.enable","parameters":{}}
> >
> > check the log and ensure no error is raised
> >
> > 5. send (removing any e-mail artefacts such as line breaks):
> >
> > {"command":"WebAuthn.addVirtualAuthenticator","parameters":{"options":{"protocol":"ctap2","transport":"usb","hasResidentKey":true,"hasUserVerification":true,"isUserVerified":true}}}
> >
> > check the log and ensure no error is raised
> >
> > 6. The last command produced an authenticator ID in its response. Copy
> > this ID from the log.
> >
> > 7, Replace in the following command all the uppercase snakecase values
> > with the copied values from before, and send it:
> >
> > {"command":"WebAuthn.addCredential","parameters":{"authenticatorId":"AUTHENTICATOR_ID","credential":{"credentialId":"CREDENTIAL_ID","isResidentCredential":true,"rpId":"CREDENTIAL_RP_ID","privateKey":"CREDENTIAL_PEM_FILE_BODY_STRING","userHandle":"CREDENTIAL_USER_HANDLE","signCount":1}}}
> >
> > check the log and ensure no error is raised
If one of these commands raises an error, open the left drawer, select
the target, input the "command" field and hit Enter -- then the
properties expand as editable form fields and can be filled in
individually. Either hit send or close the drawer and chrome will
generate a correct command in the command field.
> >
> > 8. Authenticate on the website. It worked for me.
> >
> > On reuse only the authenticator ID need be changed from the last command.
Note: This gives Chrome your PEM data but allowed me to relogin on webauthn.io on a public computer without a physical key. From exhaustive rubber ducking with google search AI.
oh no this wsan't rubber ducking i just repasted errors and code for an hour or two
Registering:
0. F12 / ctrl-shift-I / dev tools on the hardware key registration page
1. 3 dots -> More tools -> WebAuthn 2. Check Enable virtual authenticator environment 3. Click Add to create a new authenticator, optionally enable support for resident keys and user verification 3b: If the registration window is a popup and the registration flow may close the window, Sources -> Event listener breakpoints (right-hand pane) -> Load: check beforeunload and unload expand the webauthn credentials columns so they can be quickly copied out! 4. Register a device on the website => a row is added to the Credentials table. 5. Copy all the values from the table and export the PEM file (privat key) and copy the body text from it without the header and footer guards or linebreaks. This is your insecure, not-airgapped paper ID. 5b. if a breakpoint is raised resume execution to not time out, although the registration may stlil succeed if the flow times out
Authenticating: 1. F12 / ctrl-shift-I / dev tools -> gear icon / settings -> Experiments -> enable Protocol Monitor 2. Reload dev tools and go to 3 dots -> More tools -> Protocol Monitor At the bottom raw CDP commands can be sent in JSON.
3. In the lower right dropdown next to the CDP command line, set the target to Main.
4. send:
{"command":"WebAuthn.enable","parameters":{}}
check the log and ensure no error is raised
5. send (removing any e-mail artefacts such as line breaks):
{"command":"WebAuthn.addVirtualAuthenticator","parameters":{"options":{"protocol":"ctap2","transport":"usb","hasResidentKey":true,"hasUserVerification":true,"isUserVerified":true}}}
check the log and ensure no error is raised
6. The last command produced an authenticator ID in its response. Copy this ID from the log.
7, Replace in the following command all the uppercase snakecase values with the copied values from before, and send it:
{"command":"WebAuthn.addCredential","parameters":{"authenticatorId":"AUTHENTICATOR_ID","credential":{"credentialId":"CREDENTIAL_ID","isResidentCredential":true,"rpId":"CREDENTIAL_RP_ID","privateKey":"CREDENTIAL_PEM_FILE_BODY_STRING","userHandle":"CREDENTIAL_USER_HANDLE","signCount":1}}}
check the log and ensure no error is raised
If one of these commands raises an error, open the left drawer, select the target, input the "command" field and hit Enter -- then the properties expand as editable form fields and can be filled in individually. Either hit send or close the drawer and chrome will generate a correct command in the command field.
8. Authenticate on the website. It worked for me.
On reuse only the authenticator ID need be changed from the last command.
Although I am sure I found this useful for navigating my mental health and logistic problems, it is of course far more interesting to actually perform real FIDO2 on paper, if somewhat infeasible, or to write or document a general 3rd party API for webauth, or share information on a particularly hackable/securable solution.
participants (1)
-
Undescribed Horrific Abuse, One Victim & Survivor of Many