Open hats-bug-reporter[bot] opened 3 months ago
"Given that both users' profiles are valid, there is no reason for a challenger to dispute their claims. This oversight allows both users to pass through the challenge system unchallenged." There is that at least one of them is trying to register with an incorrect Humanity ID.
"While challengers can dispute duplicate profiles, they require an existing registered profile to identify the new request as a duplicate. Without an already registered profile, there is no basis for challengers to issue a challenge." Not for duplicate by for claiming the wrong Humanity ID.
As per the policy: So if one user is a first registrant, he will have ask for the default Humanity ID (which is simply the byte20 of their address). So they can't both own the same address.
As per the contest rules are excluded:
Github username: -- Twitter username: -- Submission hash (on-chain): 0x19920bb0f89a9de8f064be0d7890652d7be36f4c81bee6065e9d017c80fc03ba Severity: high
Description: Description:
A malicious actor can exploit the
claimHumanity
function to claim the samehumanityId
that another user is attempting to claim. Once both users pass the challenge period, they can use theexecuteRequest
function to claim humanity, even if they have the samehumanityId
. This results in the overwriting of the first user’s humanity claim, causing them to lose theirhumanityId
unfairly.Reasons for the Exploit:
ProofOfHumanity
Contract's Mapping: In theProofOfHumanity
contract, theaccountHumanity
variable is used to map an address to ahumanityId
. When a user claims humanity using theclaimHumanity
function with a specifichumanityId
, the_requestHumanity
function updates theaccountHumanity
mapping with the user's address:However, another user can invoke the
claimHumanity
function with the samehumanityId
. TheaccountHumanity
mapping will then store this second user’s address with the samehumanityId
. Since there are no restrictions preventing this, multiple users can have the samehumanityId
in theaccountHumanity
mapping.Simultaneous Progression Through States: With multiple users claiming the same
humanityId
, both users can simultaneously enter thevouching
state, each planning to claim humanity with the samehumanityId
. As both users submit valid proof and evidence, they can each secure the necessary votes to advance to the next state by calling theadvanceState
function. This function checks only the status of each request and whether the providedhumanityId
has an owner. If neither user has any existing humanity and thehumanityId
is unclaimed, both can easily progress through this state.Challenge System Bypass: Given that both users' profiles are valid, there is no reason for a challenger to dispute their claims. This oversight allows both users to pass through the challenge system unchallenged.
Race Condition in
executeRequest
Function: When a user calls theexecuteRequest
function to finalize their humanity claim, an issue arises if another user has also passed the challenge system. The second user can also call theexecuteRequest
function with the samehumanityId
to claim it. TheexecuteRequest
function only checks the request's status and the challenge period; it does not check if another user has already claimed humanity with the samehumanityId
. As a result, the second user can overwrite the first user's claim, unfairly causing the first user to lose theirhumanityId
.Key Issue Highlight: During the entire process, both users move through the claiming states (vouching, resolving, resolved) nearly in parallel. The overlapping or closely ending challenge periods create a scenario where challengers may miss the fact that two users are claiming the same
humanityId
. This creates a blind spot where, by the time the first user completes their claim, the second user is already outside the challenge period and cannot be contested.As noted in the out-of-scope issue: A user losing their profile if someone else manages to register a profile with the same ID on the target platform (this is not prevented by code, but by challenging duplicate profiles, even if they are on different platforms).
While challengers can dispute duplicate profiles, they require an existing registered profile to identify the new request as a duplicate. Without an already registered profile, there is no basis for challengers to issue a challenge.
Therefore, since neither user is registered while in the Resolving state, challengers cannot contest them, even if both attempt to claim the same
humanityId
.This loophole enables users to bypass the challenge system and claim the same
humanityId
.Exploitation:
A malicious user can exploit this vulnerability to take over another user's humanity. The attacker would only need to call the
createHumanity
function using thehumanityId
of a new user who is just beginning the claiming process. By providing valid evidence and creating a legitimate profile, the attacker could avoid challenges and eventually hijack the other user's humanity.To maximize their chances, the attacker can challenge the new user's claim using any 4 reasons such as "incorrect evidence" or "invalid humanity," delaying user's process and preventing him from executing his request before malicious user's own challenge period ends. Once the delay is sufficient, malicious user can proceed with his claim unopposed, successfully hijacking the new user's
humanityId
.Attack Scenario:
humanityId
using theclaimHumanity
function. TheaccountHumanity
mapping is updated with Bob's address associated with thehumanityId
.humanityId
using theclaimHumanity
function. TheaccountHumanity
mapping is updated to include Alice's address with the samehumanityId
.vouching
state, gathering vouches to claim the samehumanityId
. Since both users provide valid proof and evidence of their humanity, they obtain the necessary votes and advance to the next state by calling theadvanceState
function.executeRequest
function to finalize his humanity claim.executeRequest
function with the samehumanityId
.humanityId
unfairly.Mitigation:
executeRequest
function not only verifies the request status and challenge period but also checks for existing claims on the samehumanityId
to prevent overwriting.humanityId
simultaneously.