Skip to content

Latest commit

 

History

History
123 lines (90 loc) · 6.09 KB

File metadata and controls

123 lines (90 loc) · 6.09 KB

Passive Misty Pike

Medium

Lack of validation for attestationDetails in createAttestation function allow malicious actors to insert arbitrary or malicious data

Summary

The createAttestation function in the EthosAttestation contract does not perform adequate validation on the attestationDetails input, which can lead to data inconsistencies and potential manipulation of attestation data. Since attestationDetails is crucial to the integrity of an attestation, any lack of validation here creates opportunities for malicious actors to insert arbitrary or malicious data, potentially compromising the authenticity of attestations on the platform.

Root Cause

The createAttestation function allows users to create new attestations linked to their profiles. However, the attestationDetails input lacks thorough validation, leaving it open to possible manipulation, including the submission of empty data or maliciously structured data. In an attestation system, validating critical data inputs such as attestationDetails is essential to maintaining the reliability and security of the information stored within the contract.

The createAttestation function lacks validation for the attestationDetails parameter: https://github.com/sherlock-audit/2024-10-ethos-network/blob/main/ethos/packages/contracts/contracts/EthosAttestation.sol#L184-L260

function createAttestation(
    uint256 profileId,
    bytes32 service,
    address account,
    string memory attestationDetails,
    bytes32 evidenceHash
) public whenNotPaused {
    require(service != bytes32(0), "Service cannot be empty");
    require(account != address(0), "Account cannot be empty");

    // No validation for attestationDetails
    uint256 attestationId = ++nextAttestationId;
    bytes32 attestationHash = keccak256(abi.encodePacked(service, account));

    attestationByHash[attestationHash] = Attestation({
        attestationId: attestationId,
        profileId: profileId,
        service: service,
        account: account,
        attestationDetails: attestationDetails,
        evidenceHash: evidenceHash,
        archived: false
    });

    emit AttestationCreated(attestationId, service, account, profileId);
}

The lack of checks on attestationDetails here allows an attacker to pass an empty string, overly long strings, or even maliciously structured data in this field, which could undermine the trustworthiness of the attestation record.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

Attestations could be created with incomplete or incorrect data, compromising the integrity of user profiles.

Excessively large attestationDetails can lead to increased gas costs and potential storage inefficiencies.

An attacker could inject maliciously structured data into attestationDetails, potentially impacting frontend applications relying on this data for display or further processing.

PoC

To demonstrate this vulnerability, I use a Hardhat test where I attempt to create an attestation with empty attestationDetails or arbitrary data that would not normally be considered valid:

// Hardhat test script
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Lack of Validation for attestationDetails", function () {
  let EthosAttestation, ethosAttestation, owner, user;

  beforeEach(async function () {
    [owner, user] = await ethers.getSigners();
    EthosAttestation = await ethers.getContractFactory("EthosAttestation");
    ethosAttestation = await EthosAttestation.deploy();
    await ethosAttestation.deployed();

    // Initialize contract with a sample profile for testing
    await ethosAttestation.initialize(owner.address, user.address, owner.address);
  });

  it("should allow attestation creation with empty or invalid attestationDetails", async function () {
    // Create attestation with empty attestationDetails
    await expect(ethosAttestation.createAttestation(1, ethers.utils.formatBytes32String("Service1"), user.address, "", ethers.utils.formatBytes32String("EvidenceHash")))
      .to.emit(ethosAttestation, "AttestationCreated");

    // Check that the attestation is recorded with empty details
    const attestationHash = await ethosAttestation.getServiceAndAccountHash("Service1", user.address);
    const attestation = await ethosAttestation.getAttestationByHash(attestationHash);
    expect(attestation.attestationDetails).to.equal("");

    // Create attestation with overly long attestationDetails
    const longDetails = "x".repeat(5000);  // Exceeds reasonable limit
    await expect(ethosAttestation.createAttestation(1, ethers.utils.formatBytes32String("Service1"), user.address, longDetails, ethers.utils.formatBytes32String("EvidenceHash")))
      .to.emit(ethosAttestation, "AttestationCreated");

    // Check that the attestation is recorded with the overly long details
    const longAttestation = await ethosAttestation.getAttestationByHash(attestationHash);
    expect(longAttestation.attestationDetails.length).to.be.greaterThan(256);  // Confirm abnormal length
  });
});

Output: The contract allows the creation of an attestation with an empty attestationDetails field.

The contract also allows the creation of an attestation with overly long attestationDetails, which could pose issues during storage or retrieval and reduce the trustworthiness of attestation data.

This proves that the createAttestation function does not properly validate the attestationDetails field, allowing arbitrary and harmful data to be stored.

Mitigation

To address this issue, add input validation for attestationDetails in the createAttestation function. The following code snippet demonstrates how to enforce a minimum and maximum length for attestationDetails:

require(bytes(attestationDetails).length > 0, "Attestation details cannot be empty");
require(bytes(attestationDetails).length <= 256, "Attestation details exceed max length");

This code checks that attestationDetails is non-empty and within a reasonable maximum length, ensuring that data remains consistent and manageable.