meta-code-verify icon indicating copy to clipboard operation
meta-code-verify copied to clipboard

Warning: For sites that use HTML to render the UI, it may be possible for an attacker to bypass the check performed by Code Verify

Open meixler opened this issue 1 year ago • 1 comments

TL;DR

By design, Code Verify verifies the Javascript code associated with a web page, but does not verify the entire web page. For sites that use plain old HTML (as opposed to Javascript) to render the UI, this results in a vulnerability that may enable an attacker to bypass the check performed by Code Verify, and mount an attack of the very nature that Code Verify aims to prevent.

Details

Tampering with the Javascript that protects users’ private information in ‘zero access’ and ‘zero trust’ applications is one way for an attacker to steal the users’ private information. However, in many cases, it is possible for an attacker to steal the users’ private information simply by modifying the HTML in the root document of the web page, and without modifying any Javascript at all. Being that Code Verify only verifies the Javascript associated with a web page, and not the HTML in the root document, this creates an exploit opportunity for the attacker.

Example

Consider the following example of a simple end-to-end encrypted messaging application. As can be seen in the image of the page below, a message is entered into a form, then the message is encrypted in-browser by Javascript using the recipient’s public key, then the encrypted message is uploaded to a server, which forwards the encrypted message to the recipient.

Screenshot from 2024-03-02 19-27-26

Copied below is the HTML code and Javascript code for the above page:

sendencryptedmessage.html Screenshot from 2024-03-02 19-04-39

sendencryptedmessage.js Screenshot from 2024-03-02 19-05-10

As can be seen from the code, when the user composes a message and clicks the ‘Encrypt Message and Send’ button, the encryptandsend() Javascript function is fired, which encrypts the message and uploads the encrypted message to the server, to be forwarded to the recipient.

Now, suppose an attacker (either at the server, or in a MITM position on the network) wants to capture a message sent by a sender using this form; however, the sender is using Code Verify. Being that the sender is using Code Verify, altering the Javascript is not an option for the attacker. However, Code Verify does not verify the HTML in the root document, so the attacker modifies the HTML code in the sendencryptedmessage.html file as follows. Changes are highlighted in red:

Screenshot from 2024-03-02 19-05-40

As can be seen above, the attacker simply added the hidden attribute to the button that fires the Javascript, so that this button is now invisible. Then, the attacker wrapped the form elements inside a set of <form> tags that post to the attacker’s server, and added a submit button in place of the now invisible button that fired the Javascript.

The result: Code Verify indicates that the code is authentic, because none of the Javascript has been modified. The page looks exactly the same to the user when displayed in the user’s browser. However, when the user composes a message and clicks the ‘Encrypt Message and Send’ button, the Javascript is bypassed altogether, and the text entered in the form is posted directly to the attacker’s server.

Recommendation

This vulnerability can be mitigated if Code Verify verifies the entire web page, including the root HTML document, and all supporting files referenced by the root document. This process can be simplified if subresource integrity (SRI) is used in the root document, in all references to supporting files. In that case, simply verifying just the root document is sufficient to verify all supporting files as well; as the browser verifies the supporting files automatically via SRI, with respect to hashes of the supporting files contained in the root document. If the site is designed as a Single Page Application (SPA), then the site can be interactive, while the same verified root document (and all supporting files) remain loaded in the user’s browser throughout the user’s session.

meixler avatar Mar 03 '24 00:03 meixler

Sorry, I already deleted my previous comment, because I did not read your post properly and didnt have time to change it. However the CSP also saves us here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/form-action

However the plugin should check for CSP values for forms and inline scripts. You are right in that regard.

pkreissel avatar Mar 22 '24 17:03 pkreissel