Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Invalid

Unauthorized Asset Relisting Through Default Struct Values

Summary

It is particularly dangerous because:

  1. It breaks the fundamental trust model of the marketplace

  2. Allows creation of unauthorized listings without ownership proof

  3. Can be used to manipulate market prices and user behavior

  4. Difficult for users to distinguish legitimate from fake listings

  5. Potential for coordinated attacks to disrupt market operations

Attack Path:

  1. Attacker identifies unregistered asset address

  2. Calls relist() from address(0)

  3. Passes authorization check due to default values

  4. Creates unauthorized listing

Vulnerability Details

The vulnerability exists because

  1. The authorization check only verifies asset.seller == msg.sender

  2. For a new/non-existent asset listing, asset.seller will be the zero address

  3. If an attacker calls relist() with an unregistered asset address, the zero address check will pass if they also use address(0) as msg.sender

https://github.com/Cyfrin/2024-10-swan-dria/blob/c3f6f027ed51dd31f60b224506de2bc847243eb7/contracts/swan/Swan.sol#L197-L208

function relist(address _asset, address _buyer, uint256 _price) external {
AssetListing storage asset = listings[_asset];
// only the seller can relist the asset
if (asset.seller != msg.sender) {
revert Unauthorized(msg.sender);
}
// @bug-detected: Missing existence check for asset listing
// When listings[_asset] doesn't exist, asset.seller is address(0)
// Allows attacker to relist non-existent assets if msg.sender is address(0)
// asset must be listed
if (asset.status != AssetStatus.Listed) {
revert InvalidStatus(asset.status, AssetStatus.Listed);
}

This is dangerous for the protocol because:

  1. The listings mapping returns a default struct when accessing a non-existent key

  2. For new/unregistered assets, asset.seller will be address(0)

  3. An attacker could:

    • Call relist() with an arbitrary asset address

    • Pass the seller check if they use address(0) as msg.sender

    • Create unauthorized listings for assets they don't own

    • Potentially manipulating the market with fake listings

The impact is severe as it breaks the core trust assumption that only legitimate asset owners can create listings. This could lead to market manipulation and loss of trust in the protocol's listing mechanism.

A malicious actor could exploit this to:

  • Create fake listings

  • Manipulate market prices

  • Cause confusion for buyers

  • Potentially interfere with legitimate trades

Impact

  • Unauthorized users could potentially relist assets they don't own

  • This breaks the core assumption that only asset owners can relist their assets

Root Cause

  • The listings mapping returns a default struct for non-existent assets

  • asset.seller defaults to address(0) for new entries

  • Authorization check can be bypassed using address(0) as msg.sender

Tools Used

Manual Review

Recommendations

function relist(address _asset, address _buyer, uint256 _price) external {
AssetListing storage asset = listings[_asset];
+ require(asset.seller != address(0), "Asset does not exist");
if (asset.seller != msg.sender) {
revert Unauthorized(msg.sender);
}

Alternative Pattern

modifier onlyExistingAsset(address asset) {
require(listings[asset].seller != address(0), "Asset does not exist");
_;
}
function relist(address _asset, address _buyer, uint256 _price)
external
onlyExistingAsset(_asset)
{
// ...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.