Prepared by:
HALBORN
Last Updated 04/26/2024
Date of Engagement by: April 17th, 2023 - May 22nd, 2023
96% of all REPORTED Findings have been addressed
All findings
26
Critical
1
High
3
Medium
9
Low
11
Informational
2
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.
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.
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
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)
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 analysis | Risk level | Remediation Date |
---|---|---|
BROKEN ACCESS CONTROL ON KYC VERIFICATION | Critical | Solved - 06/06/2023 |
BROKEN ACCESS CONTROL ON ORGANIZATION ID | High | Solved - 06/06/2023 |
OTP BYPASS ON TRANSFER | High | Solved - 06/06/2023 |
MAIL SERVER MISCONFIGURATION | High | Solved - 06/06/2023 |
MALICIOUS UPLOAD DOCUMENTS FOR KYC PROCESS | Medium | Solved - 06/06/2023 |
ACCOUNT IMPERSONATION | Medium | Solved - 05/16/2023 |
NO FILE VALIDATION ON UPLOAD DOCUMENTS FOR KYC PROCESS | Medium | Solved - 05/16/2023 |
CLICKJACKING | Medium | Solved - 06/06/2023 |
FAILED TO INVALIDATE SESSION AFTER A LOGOUT | Medium | Solved - 06/06/2023 |
PRIVATE ACCESS TOKEN IN URL | Medium | Future Release - 06/06/2023 |
IMPROPER INPUT HANDLING | Medium | Solved - 06/06/2023 |
VULNERABLE THIRD PARTY DEPENDENCIES | Medium | Risk Accepted - 06/06/2023 |
LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMS ON REGISTER | Medium | Solved - 06/06/2023 |
SIMILAR HASHES ON ORGANIZATION AND USER ID | Low | Solved - 06/06/2023 |
MULTIPLE ACCOUNTS USING ONE EMAIL | Low | Solved - 06/06/2023 |
SENSITIVE DATA EXPOSURE IN LOCALSTORAGE | Low | Solved - 06/06/2023 |
PREFIX MOBILE NUMBER NEVER COULD BE UPDATED | Low | Solved - 06/06/2023 |
RESPONSE MANIPULATION | Low | Solved - 06/06/2023 |
USE OF INSECURE RANDOM FUNCTION GENERATION | Low | Solved - 06/06/2023 |
FAILED TO INVALIDATE TOKEN ON REQUEST NEW JWT | Low | Solved - 06/06/2023 |
LACK OF PREVENTION AGAINST BRUTE FORCE MECHANISMS | Low | Solved - 05/12/2023 |
DEPENDENCIES SHOULD BE PINNED TO EXACT VERSIONS | Low | Solved - 06/06/2023 |
NEGATIVE VALUES ON TRANSFER | Low | Solved - 06/06/2023 |
FRONTEND WITH VERBOSE ERRORS | Low | Solved - 06/06/2023 |
POOR AUTHENTICATION MECHANISM | Informational | Acknowledged - 06/06/2023 |
REGISTER USING DISPOSABLE EMAILS | Informational | Solved - 06/06/2023 |
// Critical
It has been observed that following endpoints did not check if Known Your Customer
(KYC) status was approved yet:
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.
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.
\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.
{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:
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.
{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,
{width="500" height="450"}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.).
{width="500" height="450"}// High
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.
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.
// High
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.
{width="500" height="450"}SOLVED: Truffles effectively resolved the issue by adding OTP header on transfer /create
request.
// High
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.
Finally, the victim sends via telegram the token received in the authentication process to the attackers. The account was fully controlled by them.
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.
{width="500" height="450"}// Medium
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.
https://staging.truffles.one
.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.
// Medium
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:
https://staging.truffles.one
.console
inspection, observe that a refreshToken
is present within the Object information array.refreshToken
as a Token Bearer and impersonate the victim user, enabling them to perform API actions on behalf of the victim.SOLVED: Truffles solved this issue, removing the user object that was displayed in console
when contact was clicked.
// Medium
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.
https://staging.truffles.one
.SOLVED: Truffles solved this issue by implementing the proper validation on file.service.ts
file.
// Medium
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:
A series of actions took place (2 clicks):
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.
{width="500" height="450"}SOLVED: Truffles solved the issue by setting X-Frame-Options headers in all applications.
{width="500" height="450"}// Medium
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:
localStore
was successfully cleared, indicating a proper session termination.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.
SOLVED: Truffles effectively solved the issue. If a user logout from browser 1, the user account is logged out in browser 2 as well.
// Medium
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.
PENDING: Truffles will implement the solution in a future release.
// Medium
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:
/halborn
./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.
{width=500 height=500}SOLVED: Truffles solved the issue. No client-side exception was detected while retesting.
// Medium
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.
RISK ACCEPTED: Truffles risk accepted the issue.
OWASP. Vulnerable and Outdated Components OWASP. Vulnerable Dependency Management Cheat Sheet
// Medium
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.
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.
SOLVED: Truffles effectively resolved the issue, implementing a Captcha.
{width="500" height="450"}// Low
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.
{width="600" height="600"}SOLVED: Truffles effectively resolved the issue, implementing a proper differenced hashes.
{width="500" height="450"}// Low
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.
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}`);
}
}
{width="600" height="600"}SOLVED: Truffles effectively resolved the issue by implementing a proper user validation.
// Low
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.
token
parameter to new sign up.for (let i = 0; i < localStorage.length; i++)
{ const key = localStorage.key(i);
const value = localStorage.getItem(key);
console.log(`${key}: ${value}`);
}
{width="500" height="450"}SOLVED: Truffles solved the issue by removing the accessToken
and refreshToken
from localstorage.
// Low
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.
{width=500 height=500}SOLVED: Truffles solved the issue enabling the field for editing the prefix number by support role user.
// Low
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.
{width=500 height=500}SOLVED: Truffles solved the issue.
// Low
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.
const newOrgObject = {
orgName: orgName,
orgType: registerEntity.orgType,
accountType: registerEntity.accountType,
TFID:
orgName.substring(0, 3) +
Math.floor(Math.random() * 1000000).toString(),
};
SOLVED: Truffles solved the issue.
generateTFID = (orgName) => {
const randomNum = randomBytes(3).readUIntBE(0, 3);
const TFID = orgName.substring(0, 3) + randomNum;
return TFID;
};
// Low
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.
SOLVED: Truffles solved the issue.
\newpage
// Low
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.
{width="600" height="600"}SOLVED: Truffles solved this issue by implementing a time counter previous next resend email.
// Low
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"
}
SOLVED: Truffles solved the issue.
\newpage
// Low
The transfer mechanism allowed for negative values in the amount field without triggering any error responses.
{width="600" height="600"}SOLVED: Truffles solved the issue.
{width="600" height="600"}// Low
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.
{width="600" height="600"}SOLVED: Truffles solved the issue.
{width="600" height="600"}// Informational
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.
ACKNOWLEDGED: Truffles risk acknowledged the issue.
// Informational
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.
{width="600" height="600"}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.
// Download the full report
* Use Google Chrome for best results
** Check "Background Graphics" in the print settings if needed