Halborn Logo

Backend / Frontend Whitebox - Truffles


Prepared by:

Halborn Logo

HALBORN

Last Updated 04/26/2024

Date of Engagement by: April 17th, 2023 - May 22nd, 2023

Summary

96% of all REPORTED Findings have been addressed

All findings

26

Critical

1

High

3

Medium

9

Low

11

Informational

2


1. INTRODUCTION

Truffles engaged Halborn to conduct a white-box pentest of their staging app: https://stagingapp.truffles.one beginning on 2023-04-17 and ending on 2023-05-22. The security assessment was scoped to GitHub source code to the Halborn team.

2. AUDIT SUMMARY

The team at Halborn was provided four weeks for the white-box pentest and assigned a full-time security engineer to audit the security of the staging's web applications. The security engineer is a penetration testing expert with advanced knowledge in web, recon, discovery & infrastructure penetration testing.

The goals of our security audits are to improve the quality of systems by testing this as white-box approach to have an attacker perspective of targeting the staging web application.

In summary, Halborn identified security risks that were mostly addressed by the Truffles team.

3. SCOPE

The following endpoints were in scope:

    • https://stagingapp.truffles.one

    • https://stagadmin.truffles.one

Source Code:

    • Truffles Support Commit ID: 0c6cc4aa2aa516fcd5451718af7b8610249cad64

    • Truffles FrontEnd Commit ID: 4e3abbc4c813a8f116368207a990e2a215ee18e6

    • Truffles BackEnd Commit ID: 4175b16d9b2394986fc5a272b5bb94a96758636a

Remediation plan:

    • Truffles Support Commit ID: 98f87279a48248d0d6ea954f62b00a4071e81fee

    • Truffles FrontEnd Commit ID: 084a674c4556f8b1a04abdb7fd1c2a349fbb6f80

    • Truffles BackEnd Commit ID: 9bd0492c2d5859c82605afde1af3e7ed913f5d74

4. TEST APPROACH & METHODOLOGY

Halborn followed a white-box approach and performed a combination of manual and automated security testing to balance efficiency, timeliness, practicality, and accuracy regarding the scope of the pentest. While manual testing is recommended to uncover flaws in logic, process and implementation; automated testing techniques assist enhance coverage of the infrastructure and can quickly identify flaws in it. The following phases and associated tools were used throughout the term of the audit:

    • Mapping Content and Functionality

    • Logic Flaws

    • Access Handling

    • Authentication/Authorization Flaws

    • Rate Limitations Tests

    • Brute Force Attempts

    • Input Handling

    • Response Manipulation

    • Source Code Review

    • Fuzzing of all input parameters

    • Multiple Type of Injection (SQL/JSON/HTML/Command)

5. RISK METHODOLOGY

Vulnerabilities or issues observed by Halborn are ranked based on the risk assessment methodology by measuring the LIKELIHOOD of a security incident and the IMPACT should an incident occur. This framework works for communicating the characteristics and impacts of technology vulnerabilities. The quantitative model ensures repeatable and accurate measurement while enabling users to see the underlying vulnerability characteristics that were used to generate the Risk scores. For every vulnerability, a risk level will be calculated on a scale of 5 to 1 with 5 being the highest likelihood or impact.
RISK SCALE - LIKELIHOOD
  • 5 - Almost certain an incident will occur.
  • 4 - High probability of an incident occurring.
  • 3 - Potential of a security incident in the long term.
  • 2 - Low probability of an incident occurring.
  • 1 - Very unlikely issue will cause an incident.
RISK SCALE - IMPACT
  • 5 - May cause devastating and unrecoverable impact or loss.
  • 4 - May cause a significant level of impact or loss.
  • 3 - May cause a partial impact or loss to many.
  • 2 - May cause temporary impact or loss.
  • 1 - May cause minimal or un-noticeable impact.
The risk level is then calculated using a sum of these two values, creating a value of 10 to 1 with 10 being the highest level of security risk.
Critical
High
Medium
Low
Informational
  • 10 - CRITICAL
  • 9 - 8 - HIGH
  • 7 - 6 - MEDIUM
  • 5 - 4 - LOW
  • 3 - 1 - VERY LOW AND INFORMATIONAL

6. SCOPE

Out-of-Scope: New features/implementations after the remediation commit IDs.

7. Assessment Summary & Findings Overview

Critical

1

High

3

Medium

9

Low

11

Informational

2

Impact x Likelihood

HAL-02

HAL-01

HAL-06

HAL-10

HAL-12

HAL-05

HAL-07

HAL-08

HAL-11

HAL-03

HAL-04

HAL-19

HAL-21

HAL-09

HAL-13

HAL-14

HAL-15

HAL-16

HAL-18

HAL-20

HAL-22

HAL-23

HAL-24

HAL-25

HAL-26

HAL-17

Security analysisRisk levelRemediation Date
BROKEN ACCESS CONTROL ON KYC VERIFICATIONCriticalSolved - 06/06/2023
BROKEN ACCESS CONTROL ON ORGANIZATION IDHighSolved - 06/06/2023
OTP BYPASS ON TRANSFERHighSolved - 06/06/2023
MAIL SERVER MISCONFIGURATIONHighSolved - 06/06/2023
MALICIOUS UPLOAD DOCUMENTS FOR KYC PROCESSMediumSolved - 06/06/2023
ACCOUNT IMPERSONATIONMediumSolved - 05/16/2023
NO FILE VALIDATION ON UPLOAD DOCUMENTS FOR KYC PROCESSMediumSolved - 05/16/2023
CLICKJACKINGMediumSolved - 06/06/2023
FAILED TO INVALIDATE SESSION AFTER A LOGOUTMediumSolved - 06/06/2023
PRIVATE ACCESS TOKEN IN URLMediumFuture Release - 06/06/2023
IMPROPER INPUT HANDLINGMediumSolved - 06/06/2023
VULNERABLE THIRD PARTY DEPENDENCIESMediumRisk Accepted - 06/06/2023
LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMS ON REGISTERMediumSolved - 06/06/2023
SIMILAR HASHES ON ORGANIZATION AND USER IDLowSolved - 06/06/2023
MULTIPLE ACCOUNTS USING ONE EMAILLowSolved - 06/06/2023
SENSITIVE DATA EXPOSURE IN LOCALSTORAGELowSolved - 06/06/2023
PREFIX MOBILE NUMBER NEVER COULD BE UPDATEDLowSolved - 06/06/2023
RESPONSE MANIPULATIONLowSolved - 06/06/2023
USE OF INSECURE RANDOM FUNCTION GENERATIONLowSolved - 06/06/2023
FAILED TO INVALIDATE TOKEN ON REQUEST NEW JWTLowSolved - 06/06/2023
LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMSLowSolved - 05/12/2023
DEPENDENCIES SHOULD BE PINNED TO EXACT VERSIONSLowSolved - 06/06/2023
NEGATIVE VALUES ON TRANSFERLowSolved - 06/06/2023
FRONTEND WITH VERBOSE ERRORSLowSolved - 06/06/2023
POOR AUTHENTICATION MECHANISMInformationalAcknowledged - 06/06/2023
REGISTER USING DISPOSABLE EMAILSInformationalSolved - 06/06/2023

8. Findings & Tech Details

8.1 BROKEN ACCESS CONTROL ON KYC VERIFICATION

// Critical

Description

It has been observed that following endpoints did not check if Known Your Customer (KYC) status was approved yet:

  • /api/v1/contacts
  • /api/v1/beneficiary
  • /api/v1/invoices
  • /api/v1/otp

KYC is a critical regulatory requirement for financial institutions and other entities dealing with customers' funds, aiming to prevent money laundering, terrorist financing, and other illegal activities. The absence of KYC checks in the verification process increases the risk of the platform being used for illicit purposes, which can lead to legal penalties, reputational damage, and even platform shutdown.

\textbf{\underline{Enumeration}:} A user possesses the potential to uncover an API endpoint that lacks proper KYC status verification. This attack can be executed through either endpoint fuzzing, wherein the user obtains an accurate response, or by manipulating a parameter within the response.

By employing the latter approach, an attacker could exploit the situation by altering the value of the KYCStatus parameter during response manipulation, thereby achieving an approved status. Consequently, this unauthorized approval would enable the attacker to trigger all permitted functionalities on the frontend web application, allowing API request to the endpoints showed above due to lack of checks including accessing contact information, beneficiary details, invoice data, and transfer endpoints. All of this can be achieved without the requirement of KYC documentation approval by support role users or the involvement of the third-party entity, "Wallex".

The implemented protection measures are solely confined to the frontend layer, rendering them susceptible to easy circumvention through response manipulation. As a result, an unauthorized user can effortlessly bypass these measures, gaining access to all accessible components within the web application.

The following proof of concept demonstrates various attacks exploiting the same vulnerability.

\textbf{\underline{Sensitive Information Exposure}:} This particular vulnerability can serve as the initial step in an attack chain, in conjunction with the HAL-02 issue, to illicitly obtain sensitive information from any targeted organization. This is possible due to the public availability of TFIDs (first 3 letters of the company name, plus randomly chosen numbers), which are utilized for adding contacts and bank beneficiaries. When the add contact request is made, the organization ID is retrieved, providing the necessary information to exploit the HAL-02 vulnerability. The overall impact is heightened by the combination of these two issues, resulting in unauthorized access to sensitive information from various organizations.

Upon successful authentication, the user receives a response containing their pertinent information. However, an attacker could exploit the web application by modifying the KYCStatus value parameter and setting it to "approved." Subsequently, upon receiving the manipulated response, the frontend reflected all functionality and mechanisms, thereby exposing them to the user, despite the lack of legitimate approval or verification.{width="500" height="450"}
The frontend application allowed the addition of contacts without conducting KYC status verification.{width="500" height="450"}
Given that the user had the capability to intercept API endpoint requests through response manipulation during the login process, a potential security vulnerability arises. Exploiting a broken access control mechanism, the user could submit a contact request without fulfilling the requirement of KYC approval.{width="500" height="450"}
The response generated from this particular request discloses the user's organization ID, which can be subsequently exploited to chain with the HAL-02 issue. By leveraging this information, an attacker could potentially gain access to sensitive data.{width="500" height="450"}

Further information on Loom Video.

\textbf{\underline{Lack of brute force mechanism on Add contact request}:} This vulnerability could be leveraged by sending many contact request invitations to organizations with TFID identifiers, resulting in an overload of pending requests for users associated with the targeted TFID organization. This is possible due to the backend's failure to verify whether the incoming TFID matches the existing ones, thereby enabling the overload of fake pending incoming requests.

Contact requests were being successfully sent without undergoing the necessary KYC approval process.{width="500" height="450"}

\textbf{\underline{Lack of checks on transfer}:} It was possible to utilize the transfer functionality without the requirement of KYC approval. This enables unauthorized access to features such as adding new beneficiaries.

The frontend application allowed for the initiation of transfers without conducting KYC status verification.{width="500" height="450"}

\textbf{\underline{Lack of checks on invoice creation}:} Breaching expected behavior, a user with an unapproved KYC status was able to create an invoice draft for a TFID organization. The anticipated process should adhere to the following steps:

  1. It was necessary for the user to have their KYC approved and a Wallex account created by a support role.
  2. The user should add a new contact by utilizing the public TFID.
  3. Furthermore, the contact should only be accepted if both organizations involved have been approved by Wallex, the banking partner.
  4. Only after fulfilling the above requirements, the user should be able to create a draft invoice.

However, the aforementioned vulnerability allowed the user to bypass these stipulations and create an invoice draft despite their KYC status not being approved.

Contrary to the intended workflow, an attack vector allowed the bypassing of all the prescribed steps by making a direct POST request to the /invoice API endpoint. This exploitation holds severe implications, as the attacker could create an invoice on behalf of an organization, falsely designating the draft as accepted without actual approval from the organization. Furthermore, through parameter tampering techniques, the attacker could manipulate the payment process, leaving the invoice pending and potentially deceiving the organization into paying without their explicit consent.

This critical vulnerability opens avenues for unauthorized individuals to exploit a pretext for fraudulent payment collection.

Despite the user not having their KYC approved, they were able to create an invoice for a TFID organization due to the presence of this issue.{width="500" height="450"}
There was evidence indicating that the user did not possess an approved KYC status.{width="500" height="450"}
There was evidence suggesting that the user successfully created an invoice.{width="500" height="450"}
There was evidence indicating that the user created an invoice without having added any contacts.{width="500" height="450"}

Lastly, the most significant impact is realized when the victim is compelled to first accept an invoice raised by the user. However,

There was evidence of the user employing parameter tampering techniques to create an invoice with an accepted status.{width="500" height="450"}
There was evidence of the invoice being in an accepted status without obtaining the necessary approval.{width="500" height="450"}
Score
Impact: 5
Likelihood: 5
Recommendation

SOLVED: The critical issue seems to have been solved with proper access control implemented on the endpoints. These endpoints were reported as broken access control due to the user with unapproved KYC being able to make POST/GET requests. Moreover, response manipulation is solved by triggering an internal error, so the malicious user could not gain advantage by disclosing the front-end components (transfers, invoice, contacts, etc.).

Forbidden resource on contacts.{width="500" height="450"}
Forbidden resource on transfer.{width="500" height="450"}
Forbidden resource on OTP sent.{width="500" height="450"}

8.2 BROKEN ACCESS CONTROL ON ORGANIZATION ID

// High

Description

By leveraging the HAL-01 vulnerability, it was possible to chain an attack and obtain the organization ID (orgId) information. Subsequently, a GET request could be sent to any organization that did not belong to the user. This chain of exploitation allowed for the retrieval of sensitive KYC information, such as personal IDs, from the targeted organization.

The severity level of this issue has been downgraded to high because the successful execution of the attack requires obtaining the orgId hash. However, this hash can be obtained by exploiting the HAL-01 vulnerability, thereby enabling the attack to be carried out.

The attack was initiated by sending a request via TFID using the HAL-01 vulnerability. As a result, the response revealed the orgId hash, which was subsequently acquired. Leveraging this obtained hash, a request was made to the endpoint /api/v1/org/63fca6a8555d51bbe1290ec4, leading to the retrieval of sensitive information pertaining to the individuals associated with the targeted organization. Consequently, the attack successfully gathered sensitive information.

Following the retrieval of the orgId hash through the exploitation of the HAL-01 vulnerability, the attacker could proceed to execute a request targeting an organization that does not belong to them. As a result, sensitive information such as IdentificationNumber was exposed and made accessible to the attacker.

The orgId hash was successfully obtained by exploiting the HAL-01 issue.{width="500" height="450"}
Having obtained the orgID, the attacker gained the ability to retrieve sensitive KYC information for any individual.{width="500" height="450"}
Score
Impact: 5
Likelihood: 4
Recommendation

SOLVED: Truffles successfully resolved the issue by implementing fix HAL-01. However, subsequent testing revealed that using the orgId hash of a different TFID, which corresponds to the user in question, resulted in a forbidden resource response.

Forbidden resource on get organization.{width="500" height="450"}

8.3 OTP BYPASS ON TRANSFER

// High

Description

It was possible for an attacker to initiate a request to the endpoint /api/v1/transfer/quote to create a new quote and subsequently use /api/v1/transfer/create to perform outgoing transfers without the requirement of OTP verification. This vulnerability allowed a user to manually execute these actions without having to send an OTP request beforehand, as the transfer quote did not verify if an OTP was sent.

The impact of this issue was particularly concerning in cases where unauthorized access to a user account has been obtained. In such instances, the additional security layer of two-factor authentication (2FA) was rendered unnecessary, enabling the unauthorized transfer of funds to a beneficiary account.

The user could manually send a quote request to the API backend without undergoing OTP verification.{width="500" height="450"}
The user had the capability to manually send a create request to the API backend using the quote ID obtained from the previous request.{width="500" height="450"}
Finally, the user successfully initiated an outgoing transfer without the requirement of a two-factor authentication (2FA) OTP.{width="500" height="450"}
Score
Impact: 4
Likelihood: 4
Recommendation

SOLVED: Truffles effectively resolved the issue by adding OTP header on transfer /create request.

OTP Header.{width="500" height="450"}

8.4 MAIL SERVER MISCONFIGURATION

// High

Description

Truffles mail server contained multiple misconfigurations, allowing an attacker to impersonate emails as Truffles and performing scams/fraud/phishing users, which may result in financial and customer loss.

Furthermore, an attacker could exploit the aforementioned vulnerability in conjunction with (HAL-08) to execute a specifically targeted attack against corporate users.

An email was sent under false pretences, purporting to originate from the email address admin@truffles.one.{width="500" height="450"}
The individual identified as the victim, with the email address alvaro.macias@halborn.com, received an email from the attacker, who had assumed the identity of admin@truffles.one.{width="500" height="450"}

Finally, the victim sends via telegram the token received in the authentication process to the attackers. The account was fully controlled by them.

Score
Impact: 4
Likelihood: 4
Recommendation

SOLVED: Truffles effectively resolved the issue. Consequently, due to the non-delivery of the email, the targeted user did not receive the message sent by the attacker.

The email failed to achieve deliverability. It appeared that Truffles.one was not the legitimate sender of the message.{width="500" height="450"}

8.5 MALICIOUS UPLOAD DOCUMENTS FOR KYC PROCESS

// Medium

Description

An attacker could upload malicious PDF files within the KYC process. This presents a significant impact as it introduces the risk of unauthorized code execution or the dissemination of malicious content. The presence of these malicious files within the KYC process poses a threat to the security and integrity of the system and potentially compromises sensitive information.

Know Your Customer (KYC) is a critical regulatory requirement for financial institutions and other entities dealing with customers' funds, aiming to prevent money laundering, terrorist financing, and other illegal activities. Since the KYC checks the uploaded documents, this increases the risk of the user could be infected by malicious malware executed on corporate laptop.

  1. Navigate to https://staging.truffles.one.
  2. Create an account.
  3. Select a malicious .pdf file and upload as a KYC document.
CVE-2018-4993, a known security vulnerability, was uploaded to the client backend disguised as a KYC document. Malicious PDF document uploaded on dashboard. The infected PDF file can be downloaded by a support role user, exposing them to the risk of infection. The uploaded PDF file underwent VirusTotal detection, revealing the presence of a potential virus or malware.
Score
Impact: 4
Likelihood: 3
Recommendation

SOLVED: Truffles effectively resolved the issue using AWS WAF for scanning all files before uploading to the serve. Also, they are planning to integrate Cloudflare WAF on top of AWS for better malware scanning.

8.6 ACCOUNT IMPERSONATION

// Medium

Description

Within the support role privileges, there existed a potential vulnerability that enables the acquisition of the refreshToken for any recently registered user. This allowed the support role user to impersonate the target account by utilizing the obtained refreshToken. As a consequence, the support role user gained unauthorized access to the victim's account, potentially resulting in unauthorized actions and compromising the confidentiality, and integrity of user data.

The following steps outline a scenario involving potential security vulnerabilities:

  1. Access the URL https://staging.truffles.one.
  2. Log in as a support role user.
  3. Open the browser console and examine the contact information associated with a newly registered user.
  4. During the console inspection, observe that a refreshToken is present within the Object information array.
  5. The support role user can exploit this refreshToken as a Token Bearer and impersonate the victim user, enabling them to perform API actions on behalf of the victim.
  6. These actions can potentially involve fraudulent activities, such as sending a POST request to accept an invoice and initiate payment, resulting in severe consequences and a heightened impact.
The refreshToken belonging to a user has been successfully retrieved. The token information could be extracted using commonly available tools and techniques. The support role user could gain unauthorized access to user accounts by utilizing the refreshToken. This allowed the support role user to impersonate the user and perform potentially malicious API requests. There was evidence to indicate that the support role user cannot access the user's invoice using their own token.
Score
Impact: 4
Likelihood: 2
Recommendation

SOLVED: Truffles solved this issue, removing the user object that was displayed in console when contact was clicked.

8.7 NO FILE VALIDATION ON UPLOAD DOCUMENTS FOR KYC PROCESS

// Medium

Description

The file types allowed to be uploaded should be restricted to only those that are necessary for business functionality. A malicious actor was able to upload non-image files.

  1. Navigate to https://staging.truffles.one.
  2. Create an account.
  3. Select an executable .dmg file and upload as a KYC document.
File uploaded Web application tried to render it.
Score
Impact: 4
Likelihood: 3
Recommendation

SOLVED: Truffles solved this issue by implementing the proper validation on file.service.ts file.

8.8 CLICKJACKING

// Medium

Description

Clickjacking is a malicious technique that permits to load the vulnerable application inside a frame under attacker's control. This could allow injecting malicious actions inside the legitimates.

The lack of X-Frame-Options or Content-Security-Policy ‘frame-ancestors’ headers on server's responses made the application vulnerable to potential Clickjacking attacks.

The attacker successfully initiated the worldcheck process with just two clicks, exploiting the victim's actions. It was important to note that the worldcheck process is a manual KYC procedure implemented on the Truffles support side specifically for organization members. This process exists because Wallex, the banking partner, only performs KYC for the organization's admin and KYB (Know Your Business) checks for the organization itself. However, the attacker was able to bypass these limitations and initiate the worldcheck process.

Requirements:

  • Attacker: operator user.
  • Victim: support user.
  • Third-party affected: admin user.

A series of actions took place (2 clicks):

  • The perpetrator initiated the creation of a malicious website and disseminates the link to targeted victims.
  • The attacker as belongs to the organization, known the ID.
  • The first position will always be the admin of the organization. This click edited the info of account.
  • Finally, using only two clicks, the victim could perform the POST API request to initialize world check of admin user account.

Malicious website injecting the iframe:

<script>window.addEventListener("message", function(e){ var data, childFrame = document.getElementById("childFrame"); try { data = JSON.parse(e.data); } catch(e){ data = {}; } if(!data.clickbandit){ return false; } childFrame.style.width = data.docWidth+"px";childFrame.style.height = data.docHeight+"px";childFrame.style.left = data.left+"px";childFrame.style.top = data.top+"px";}, false);</script><iframe src="https://stagadmin.truffles.one/support/63fca6a8555d51bbe1290ec4" scrolling="no" style="width:1256px;height:775px;position:absolute;left:-816px;top:-54px;border:0;" frameborder="0" sandbox="allow-same-origin allow-scripts allow-forms" id="childFrame" onload="parent.postMessage(JSON.stringify({clickbandit:1}),'*')"></iframe>

The consequences of this attack were significant, resulting in the victim's world check without their consent. The attack's complexity was heightened by the necessity of creating a credible pretext and leveraging social engineering techniques to elicit the victim's clicks, ultimately diminishing the probability of successful exploitation and warranting a moderate level of severity for the vulnerability.

Clickjacking issue.{width="500" height="450"}
A malicious website has employed a clickjacking attack to compromise the security of the web application.{width="500" height="450"}
The clickjacking attack was successfully executed, allowing the attacker to perform a POST API request using the support authentication bearer token. This attack was carried out in just two clicks, making it an effective and sophisticated pretexting attack.{width="500" height="450"}
Score
Impact: 4
Likelihood: 3
Recommendation

SOLVED: Truffles solved the issue by setting X-Frame-Options headers in all applications.

Attacker couldn't clickjacking to the victim.{width="500" height="450"}

8.9 FAILED TO INVALIDATE SESSION AFTER A LOGOUT

// Medium

Description

It has been discovered that Truffles web application exhibited a flaw in its session management. Specifically, the application failed to invalidate previously created sessions even after a user had successfully logged out. As a result, the user's session persisted, posing a significant security risk, especially if the user's JWT (JSON Web Token) was compromised.

This vulnerability allows an attacker who has gained unauthorized access to a user's JWT to maintain full control over the victim's account. Despite the user's attempt to log out, the active session remains intact, granting the attacker ongoing access and potentially allowing them to perform malicious actions on behalf of the victim.

To replicate this issue, it conducted a test using two different browsers and the same user account. The steps were as follows:

  1. Logged in to the user account using the first browser.
  2. Simultaneously logged in to the same user account using the second browser.
  3. On the first browser, initiated the log-out process. Upon inspection of the browser's development tools, it is verified that the localStore was successfully cleared, indicating a proper session termination.
  4. However, on the second browser, the session remained active despite the log-out attempt. This indicates a failure in properly invalidating the session, allowing it to persist even after a user has logged out from one browser.

  5. CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N

Score
Impact: 3
Likelihood: 3
Recommendation

SOLVED: Truffles effectively solved the issue. If a user logout from browser 1, the user account is logged out in browser 2 as well.

8.10 PRIVATE ACCESS TOKEN IN URL

// Medium

Description

Sensitive information within URLs may be logged in various locations, including the user's browser, the web server and any forward or reverse proxy servers between the two endpoints. URLs may also be displayed on-screen, bookmarked or emailed around by users. Placing secrets into the URL increases the risk that they will be captured by an attacker.

token-url.png
Score
Impact: 4
Likelihood: 2
Recommendation

PENDING: Truffles will implement the solution in a future release.

8.11 IMPROPER INPUT HANDLING

// Medium

Description

Improper handling of errors can introduce a variety of security problems for a website. Web applications frequently generate error conditions during normal operation. Out of memory, null pointer exceptions, system call failure, database unavailable, network timeout, and hundreds of other common conditions can cause errors to be generated.

During the audit, it has been discovered multiple instances of client-side exception errors within the system. These errors occur on the client side, typically within the user's web browser or application, and can negatively impact the user experience and the overall functionality of the system.

Tested Endpoint: https://stagingapp.truffles.one

The exception can be triggered by following these steps:

  1. The user logs in to the web application using their credentials.
  2. After successful login, the user navigates to a random endpoint within the application, such as /halborn.
  3. If the user attempts to return to the /dashboard page or any other desired location, a client-side exception is triggered, resulting in the user being redirected back to the login page.

This exception disrupts the expected user experience, as the user is forced to log in again to regain access to the application. This behavior can be particularly impactful for users with the support role, as they may encounter difficulties accessing the "/support" endpoint and performing their assigned tasks.

Client-side exception has occurred.{width=500 height=500}
Score
Impact: 4
Likelihood: 3
Recommendation

SOLVED: Truffles solved the issue. No client-side exception was detected while retesting.

8.12 VULNERABLE THIRD PARTY DEPENDENCIES

// Medium

Description

The scoped repository uses multiple third-party dependencies. Using vulnerable third-party libraries can result in security vulnerabilities in the project that can be exploited by attackers. This can result in data breaches, theft of sensitive information, and other security issues. However, some of them were affected by public-known vulnerabilities that may pose a risk to the global application security level.

Multiple vulnerable dependencies in backend repository
Score
Impact: 4
Likelihood: 2
Recommendation

8.13 LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMS ON REGISTER

// Medium

Description

The authentication page of the web application features a registration form; however, it lacks a captcha validation mechanism. Consequently, this absence of captcha verification allowed users to submit an excessive number of requests, leading to an overload of new user creations on the support endpoint located at stagadmin.truffles.one.

The repercussions of this issue could disrupt the workflow of support personnel, particularly in the areas of KYC approval and the verification of uploaded documents for legitimate users.

During the execution of the script, it was imperative to effectively manage a rotating proxy system that incorporates multiple VPN connections.

import requests

headers = {
    'Host': 'stagingapi.truffles.one',
    'User-Agent': 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))',
    'Accept': 'application/json',
    'Accept-Language': 'en-US,en;q=0.5',
    # 'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/json',
    # 'Content-Length': '328',
    'Origin': 'https://stagingapp.truffles.one',
    'Referer': 'https://stagingapp.truffles.one/',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-site',
    # Requests doesn't support trailers
    # 'Te': 'trailers',
    'Connection': 'close',
}

for i in range(1,100):
    json_data = {
        'accountType': 'company',
        'phoneCode': '+1',
        'residentialCountry': {
            'country': 'Spain',
            'countryCode': '34',
            'isoCode2': 'ES',
            'isoCode3': 'ESP',
        },
        'email': 'qum123-%s@yopmail.com' % str(i),
        'firstName': '%s' % str(i),
        'lastName': 'AAA',
        'mobileNumber': 638158711,
        'orgName': 'PWN%s' % str(i),
        'orgType': 'tech',
        'title': 'Mr',
        'language': 'en',
        'terms': False,
    }

    print(i)


    response = requests.post('https://stagingapi.truffles.one/api/v1/auth/register', headers=headers, json=json_data, verify=True)

    print(response.text)

# Following prints your normal public IP
print(requests.get("http://httpbin.org/ip").text)


If a huge number of requests per second were sent, the webflow application bans the traffic, serving a response with HTTP code 429 and error code Too Many Requests. However, this mechanism protects by banning the IP. With sophisticated tools that handle a rotated proxy with several VPN connections, this protection can be bypassed, as shown in the next screenshot.

Script execution and bypassing rate limit with a rotated proxy.{width="600" height="600"}
Rate limiting bypassed.

Following the attack, the support endpoint experienced a significant influx of fraudulent user registrations, resulting in disruptions to the support team's workflow for KYC document approval and the creation of accounts with the Wallex third-party service provider.

The script had the capability to rapidly generate an unlimited number of fake user accounts within a condensed time period.
Score
Impact: 3
Likelihood: 3
Recommendation

SOLVED: Truffles effectively resolved the issue, implementing a Captcha.

GCaptcha implemented.{width="500" height="450"}

8.14 SIMILAR HASHES ON ORGANIZATION AND USER ID

// Low

Description

It has come to attention that the _id parameter associated with a user and the corresponding orgId parameter share identical values, differing only in the last byte. Although no known exploits have been identified thus far, this issue carries a potential vulnerability that may be leveraged by attackers in future releases featuring new API endpoints. If an attacker gains access to the orgID, they could retrieve the user's ID and exploit it for malicious purposes, such as accessing sensitive information.

The evidence of user1's hashes.{width="600" height="600"}
The evidence of user2's hashes.
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles effectively resolved the issue, implementing a proper differenced hashes.

Different hashes.{width="500" height="450"}

8.15 MULTIPLE ACCOUNTS USING ONE EMAIL

// Low

Description

It has been observed a logical overlook in the sign-up. There was wrong condition while checking for existing users through email using AND statement.

/src/auth/auth.service.ts

async register(registerEntity: RegisterEntity): Promise<string | void> {
    try {
      await this.loadSecret();
      const { email, orgName } = registerEntity;
      const user = await this.userService.findByEmailForRegister(email);
      const org = await this.orgService.findByNameForRegister(orgName);
      if (user && org) {
        throw new BadRequestException('User email or Org already exist');
      }
      const newOrgObject = {
        orgName: orgName,
        orgType: registerEntity.orgType,
        accountType: registerEntity.accountType,
        TFID:
          orgName.substring(0, 3) +
          Math.floor(Math.random() * 1000000).toString(),
      };

      const newOrg = await this.orgService.create(newOrgObject);
      const registerUserData: CreateAuthDto = {
        role: 'onboarder',
        orgID: newOrg.id,
        email: email,
        orgName: orgName,
        title: registerEntity.title,
        firstName: registerEntity.firstName,
        lastName: registerEntity.lastName,
        mobileNumber: registerEntity.mobileNumber,
        language: registerEntity.language,
        residentialCountry: registerEntity.residentialCountry.country,
        residentialCountryIso2: registerEntity.residentialCountry.isoCode2,
        residentialCountryIso3: registerEntity.residentialCountry.isoCode3,
        phoneCode: registerEntity.residentialCountry.countryCode,
        accountType: registerEntity.accountType,
      };
      const createdUser = await this.userService.create(registerUserData);
      return this.sendMagicLink(createdUser, createdUser.role);
    } catch (err) {
      throw new BadRequestException(`Register User : ${err}`);
    }
  }
The evidence of ALICE user register{width="600" height="600"}
The evidence of BOB user register{width="600" height="600"}
The evidence of both accounts created using same email address. The evidence of both accounts created using same email address.
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles effectively resolved the issue by implementing a proper user validation.

8.16 SENSITIVE DATA EXPOSURE IN LOCALSTORAGE

// Low

Description

Secure or sensitive data should not be stored persistently in browser data stores as this may permit information leakage on shared systems and could result in account takeover by exfiltration of the jwtToken. Sensitive data is stored in localStorage located in state key. This data includes jwtToken.

  1. Receive the email with the token parameter to new sign up.
  2. Open the Developer Tools (usually the F12 button).
  3. Go to the Local Storage tab (e.g. Storage -> Local Storage).
  4. An alternative option is to go to the Console section and enter the following code:
for (let i = 0; i < localStorage.length; i++) 
{ const key = localStorage.key(i);
const value = localStorage.getItem(key); 
console.log(`${key}: ${value}`);
}
localstorage-jwt.png{width="500" height="450"}
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue by removing the accessToken and refreshToken from localstorage.

Tokens no present on localstorage.{width="500" height="450"}

8.17 PREFIX MOBILE NUMBER NEVER COULD BE UPDATED

// Low

Description

The inability for support role users to change the prefix of a mobile number has been identified as an ongoing issue. This limitation was observed without the phoneCode parameter within the update API request, which prevents support role users from modifying the mobile number prefix.

The impact of this issue was notable, as support role users were unable to change the prefix of any mobile numbers associated with user accounts. This poses a challenge, particularly when performing transfers that require two-factor authentication (2FA) through the sending of SMS messages containing OTP codes. The locked accounts hinder the smooth processing of transfers, causing inconvenience for both the users and the support team.

Prefix number field disabled.{width=500 height=500}
Score
Impact: 1
Likelihood: 4
Recommendation

SOLVED: Truffles solved the issue enabling the field for editing the prefix number by support role user.

8.18 RESPONSE MANIPULATION

// Low

Description

The current way the front end handles the user session was by directly requesting the backend the user profile without any authentication mechanism. So, it was possible to modify the request or the response to make the front end trust the input data and load the view of a different user, or even a user with more privileges.

It was important to mention that it does not mean that when doing this, it was possible to impersonate the user session. However, it was possible to leak information about administrative tasks because of reflected on the front-end UI.

Changing onboard role to superadmin.{width=500 height=500}
After response manipulation, the user is superadmin.{width=500 height=500}
Response manipulation leak administrative KYC process steps.{width=500 height=500}
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

8.19 USE OF INSECURE RANDOM FUNCTION GENERATION

// Low

Description

The application uses a potentially insecure function to nonce generation and other mechanism, which might lead to potential security risks. The application utilizes the Math.random() function to generate random numbers. The Math.random() function is not cryptographically secure and can be exploited by attackers to predict TFID for organization, compromising the other random sequence generation.

It was important to note that under certain circumstances, the TFID had the potential to generate identical identifiers for different organization names, leading to a collision in the assigned IDs.

backend/src/auth/auth.service.ts

const newOrgObject = {
        orgName: orgName,
        orgType: registerEntity.orgType,
        accountType: registerEntity.accountType,
        TFID:
          orgName.substring(0, 3) +
          Math.floor(Math.random() * 1000000).toString(),
      };
Score
Impact: 3
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

generateTFID = (orgName) => {
    const randomNum = randomBytes(3).readUIntBE(0, 3);
    const TFID = orgName.substring(0, 3) + randomNum;

    return TFID;
  };

8.20 FAILED TO INVALIDATE TOKEN ON REQUEST NEW JWT

// Low

Description

During the assessment, it has been observed that the previously authenticated JWT Token did not get invalidated on request new JWT token. If the JWT Token was exposed to any user by some misconfiguration/vulnerability, an attacker could maintain access to the user's account for the longest amount of time, as the JWT will not get invalidated on new token created, this could lead to complete account takeover of a user account.

Both JWT active.
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

\newpage

8.21 LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMS

// Low

Description

The web page contains a form on the authentication page that allowed a user to sign in. Nevertheless, it did not have a captcha on the form that validates the request in order to prevent the excessive submissions sent by a user, resulting in an overloaded inbox.

Authentication without Captcha.{width="600" height="600"}
Intruder attack was performed using a web proxy. The user identified as the victim has received multiple emails containing subscription requests.
Score
Impact: 3
Likelihood: 2
Recommendation

SOLVED: Truffles solved this issue by implementing a time counter previous next resend email.

8.22 DEPENDENCIES SHOULD BE PINNED TO EXACT VERSIONS

// Low

Description

The application contains some external dependencies, some of which are not pinned to an exact version but set to a compatible version (^x.x.x). This can potentially enable dependency attacks, as observed with the event-stream package with the Copay Bitcoin Wallet.

Backend repository:

"dependencies": {
    "@aws-sdk/client-s3": "^3.267.0",
    "@aws-sdk/s3-request-presigner": "^3.278.0",
    "@fastify/csrf-protection": "^6.1.0",
    "@fastify/formbody": "^7.4.0",
    "@fastify/helmet": "^10.1.0",
    "@fastify/multipart": "^7.4.0",
    "@fastify/static": "^6.6.1",
    "@nestjs-modules/mailer": "^1.8.1",
    "@nestjs/axios": "^1.0.1",
    "@nestjs/common": "^9.0.0",
    "@nestjs/config": "^2.3.1",
    "@nestjs/core": "^9.0.0",
    "@nestjs/devtools-integration": "^0.1.4",
    "@nestjs/jwt": "^9.0.0",
    "@nestjs/mapped-types": "*",
    "@nestjs/microservices": "^9.2.1",
    "@nestjs/mongoose": "^9.2.1",
    "@nestjs/passport": "^9.0.0",
    "@nestjs/platform-express": "^9.3.9",
    "@nestjs/platform-fastify": "^9.2.1",
    "@nestjs/platform-socket.io": "^9.2.1",
    "@nestjs/schedule": "^2.2.1",
    "@nestjs/swagger": "^6.3.0",
    "@nestjs/throttler": "^3.1.0",
    "@nestjs/typeorm": "^9.0.1",
    "@nestjs/websockets": "^9.2.1",
    "@pinata/sdk": "^2.1.0",
    "@truffle/hdwallet-provider": "^2.1.9",
    "@types/cryptr": "^4.0.1",
    "@types/multer": "^1.4.7",
    "@types/winston": "^2.4.4",
    "aws-sdk": "^2.1287.0",
    "axios": "^1.2.2",
    "bcryptjs": "^2.4.3",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.14.0",
    "country-calling-code": "^0.0.3",
    "crypto-js": "^4.1.1",
    "cryptr": "^6.2.0",
    "ethereumjs-tx": "^2.1.2",
    "ethers": "^6.1.0",
    "fastify": "^4.11.0",
    "handlebars": "^4.7.7",
    "merkletreejs": "^0.3.9",
    "mime-types": "^2.1.35",
    "moment": "^2.29.4",
    "mongodb-memory-server": "^8.12.2",
    "mongoose": "^6.10.1",
    "nestjs-redoc": "^2.2.2",
    "nodemailer": "^6.9.0",
    "passport": "^0.6.0",
    "passport-jwt": "^4.0.0",
    "passport-local": "^1.0.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0",
    "swagger-themes": "^1.2.28",
    "truffles-web3": "0.0.7",
    "typegoose": "^5.9.1",
    "typeorm": "^0.3.11",
    "uuid": "^9.0.0",
    "web3": "^1.9.0",
    "web3-utils": "^1.9.0",
    "winston": "^3.8.2",
    "winston-daily-rotate-file": "^4.7.1"
  }

Frontend repository:

"dependencies": {
    "@cyntler/react-doc-viewer": "^1.10.3",
    "@material-tailwind/react": "1.2.4",
    "@types/react-datepicker": "^4.8.0",
    "antd": "^5.1.7",
    "axios": "^1.3.1",
    "country-calling-code": "^0.0.3",
    "daisyui": "^2.46.1",
    "date-fns": "^2.29.3",
    "formik": "^2.2.9",
    "framer-motion": "^8.1.9",
    "moment": "^2.29.4",
    "next": "latest",
    "notistack": "^3.0.1",
    "react": "18.2.0",
    "react-datepicker": "^4.8.0",
    "react-doc-viewer": "^0.1.5",
    "react-documents": "^1.2.1",
    "react-dom": "18.2.0",
    "react-icons": "^4.7.1",
    "react-query": "^3.39.3",
    "react-redux": "^8.0.5",
    "react-select": "^5.7.0",
    "react-toastify": "^9.1.1",
    "recharts": "^2.4.3",
    "yup": "^0.32.11"
  }

Support repository:

"dependencies": {
    "@cyntler/react-doc-viewer": "^1.13.0",
    "@material-tailwind/react": "^1.4.2",
    "@types/node": "18.15.11",
    "@types/react": "18.0.31",
    "@types/react-dom": "18.0.11",
    "antd": "^5.1.7",
    "axios": "^1.3.1",
    "country-calling-code": "^0.0.3",
    "daisyui": "^2.46.1",
    "date-fns": "^2.29.3",
    "eslint": "8.37.0",
    "eslint-config-next": "13.2.4",
    "formik": "^2.2.9",
    "framer-motion": "^8.1.9",
    "moment": "^2.29.4",
    "next": "latest",
    "notistack": "^3.0.1",
    "react": "18.2.0",
    "react-datepicker": "^4.8.0",
    "react-doc-viewer": "^0.1.5",
    "react-documents": "^1.2.1",
    "react-dom": "18.2.0",
    "react-icons": "^4.7.1",
    "react-query": "^3.39.3",
    "react-redux": "^8.0.5",
    "react-select": "^5.7.0",
    "react-toastify": "^9.1.1",
    "recharts": "^2.4.3",
    "typescript": "5.0.2",
    "yup": "^0.32.11"
  }
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

\newpage

8.23 NEGATIVE VALUES ON TRANSFER

// Low

Description

The transfer mechanism allowed for negative values in the amount field without triggering any error responses.

Request made with negative amount.{width="600" height="600"}
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

Bad request error.{width="600" height="600"}

8.24 FRONTEND WITH VERBOSE ERRORS

// Low

Description

Truffles web app backend API responded to errors leaking more information about the backend. This behavior presents more information than it should to the user.

Regex pattern verbose error.{width="600" height="600"}
Score
Impact: 2
Likelihood: 2
Recommendation

SOLVED: Truffles solved the issue.

No Regex pattern verbose error.{width="600" height="600"}

8.25 POOR AUTHENTICATION MECHANISM

// Informational

Description

Poor or missing authentication schemes allow an adversary to anonymously execute functionality within the web app or backend server used by the web app. In this particular case, the web application lacks any password protection mechanism. The sole authentication mechanism implemented was email login, which relies on the issuance of a link sent to the user's email address. However, if a user's email account is compromised, an attacker could exploit this vulnerability to authenticate themselves as the victim on the web application.

It was important to note that even a compromise of the superadmin role account email would result in the compromise of the entire web application. This vulnerability arises due to the utilization of the same authentication process for both low-privileged and high-privileged accounts.

The login mechanism exclusively utilized the email address as the sole means of authentication.
Score
Impact: 1
Likelihood: 2
Recommendation

ACKNOWLEDGED: Truffles risk acknowledged the issue.

OWASP. Authentication

8.26 REGISTER USING DISPOSABLE EMAILS

// Informational

Description

It was found that Truffles web application allowed the use of disposable email addresses (e.g. 'yopmail.com') when registering users. It is well known that these types of email addresses could be associated with scams or malicious users.

Registered using disposable email.{width="600" height="600"}
Score
Impact: 1
Likelihood: 2
Recommendation

SOLVED: Truffles solved this issue by implementing the proper validation on email register.

async checkDisposableEmail(email: string): Promise<boolean> {
    const res = axios.get(`https://open.kickbox.com/v1/disposable/${email}`);
    return (await res).data.disposable;
  }

Halborn strongly recommends conducting a follow-up assessment of the project either within six months or immediately following any material changes to the codebase, whichever comes first. This approach is crucial for maintaining the project’s integrity and addressing potential vulnerabilities introduced by code modifications.