sherlock-audit / 2024-10-ethos-network-judging

0 stars 0 forks source link

heeze - Only the author address of a review can restore and archive the review. #212

Open sherlock-admin3 opened 3 weeks ago

sherlock-admin3 commented 3 weeks ago

heeze

Medium

Only the author address of a review can restore and archive the review.

Summary

The EthosReview::archiveReview and EthosReview::restoreReview functions can only be called by the author address of the review, but the review is linked to the author's profile which is an issue since an address can be removed from a profile

Root Cause

In EthosReview::archiveReview and EthosReview::restoreReview allowing only the author's address of a review to archive and restore the review.

Internal pre-conditions

External pre-conditions

No response

Attack Path

  1. User A registers account B by calling EthosProfile::registerAddress to their profile.
  2. account B calls EthosReview::addReview and adds a review to the profile
  3. account B is compromised and User A calls EthosProfile::deleteAddressAtIndex to remove account B
  4. User A will be unable to archive the review or restore it if account B archives it meanwhile account B can still archive and restore the review for the profile they aren't associated with anymore as they are the author.

Impact

User A will lose the capability of archiving and restoring the review as the address that authored it has been removed from the profile. While account B will still be able to archive and restore the reviews.

PoC

it('POC -- remove review author', async () => {
      const { ethosProfile, PROFILE_CREATOR_0, EXPECTED_SIGNER, OTHER_0, OWNER, ethosReview, OTHER_1 } =
        await loadFixture(deployFixture);

      const profileId = String(2);
      const rand = '123';
      const signature = await common.signatureForRegisterAddress(
        OTHER_0.address,
        profileId,
        rand,
        EXPECTED_SIGNER,
      );

      await ethosProfile.connect(OWNER).inviteAddress(PROFILE_CREATOR_0.address);
      await ethosProfile.connect(PROFILE_CREATOR_0).createProfile(1);

      await ethosProfile
        .connect(PROFILE_CREATOR_0)
        .registerAddress(OTHER_0.address, profileId, rand, signature);

      const adddresses = await ethosProfile.addressesForProfile(2);
      expect(adddresses.length).to.be.equal(2, 'should be 2 addresses');

      expect(adddresses[0]).to.be.equal(PROFILE_CREATOR_0.address, 'wrong address[0]');
      expect(adddresses[1]).to.be.equal(OTHER_0.address, 'wrong address[1]');

      const params = {
        score: Score.Positive,
        subject: OTHER_1.address,
        paymentToken: ethers.ZeroAddress,
        comment: defaultComment,
        metadata: defaultMetadata,
        attestationDetails: {
          account: '',
          service: '',
        } satisfies AttestationDetails,
      };

      await ethosReview
        .connect(OTHER_0)
        .addReview(
          params.score,
          params.subject,
          params.paymentToken,
          params.comment,
          params.metadata,
          params.attestationDetails
        );

      let review = await ethosReview.reviews(0);
      expect(review.archived).to.equal(false, 'wrong before');

      await ethosReview.connect(OTHER_0).archiveReview(0);

      review = await ethosReview.reviews(0);
      expect(review.archived).to.equal(true, 'wrong after');

      await ethosProfile.connect(PROFILE_CREATOR_0).deleteAddressAtIndex(1);

      const profileCreatorAddresses = await ethosProfile.addressesForProfile(2);
      expect(profileCreatorAddresses.length).to.be.equal(1);
      expect(profileCreatorAddresses[0]).to.be.equal(PROFILE_CREATOR_0.address);
      await expect(ethosReview.connect(PROFILE_CREATOR_0).restoreReview(0)).to.be.revertedWithCustomError(ethosReview, 'UnauthorizedArchiving')
      .withArgs(0);

    });

Mitigation

Only addresses linked to a profile should be able to restore and archive a review on behalf of the profile.