-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attacker can modify position (hedge or close) of any user #555
Comments
@alex-ppg If a user has enabled modification of their position & has actually made a change by calling the In the check shown below, since the attacker has set File: GammaTradeMarket.sol
408: function _getOrInitPosition(uint256 positionId, bool isCreatedNew, address trader, uint64 pairId)
...
425: if (userPosition.owner != trader) {
426: revert SignerIsNotPositionOwner();
427: }
... The attacker can now change any of the values inside the File: GammaTradeMarketLib
function saveUserPosition(GammaTradeMarketLib.UserPosition storage userPosition, GammaModifyInfo memory modifyInfo)
....
// auto close condition
userPosition.expiration = modifyInfo.expiration;
userPosition.lowerLimit = modifyInfo.lowerLimit;
userPosition.upperLimit = modifyInfo.upperLimit;
// auto hedge condition
userPosition.maximaDeviation = modifyInfo.maximaDeviation;
userPosition.hedgeInterval = modifyInfo.hedgeInterval;
userPosition.sqrtPriceTrigger = modifyInfo.sqrtPriceTrigger;
userPosition.auctionParams.minSlippageTolerance = modifyInfo.minSlippageTolerance;
userPosition.auctionParams.maxSlippageTolerance = modifyInfo.maxSlippageTolerance;
userPosition.auctionParams.auctionPeriod = modifyInfo.auctionPeriod;
userPosition.auctionParams.auctionRange = modifyInfo.auctionRange;
... |
Hey @Shubh0412, thanks for contributing to the PJQA process! This represents a validation repository finding and as such was not evaluated by me directly. I do not believe the issue is relevant as the interaction described would consume the signature via a Permit 2 transfer preventing its replayability. |
Hello @alex-ppg, According to the official permit2 docs
& also here
The above statements are verified in File: GammaTradeMarket.sol
408: function _getOrInitPosition(uint256 positionId, bool isCreatedNew, address trader, uint64 pairId)
...
425: if (userPosition.owner != trader) {
426: revert SignerIsNotPositionOwner();
427: }
... But the File: GammaTradeMarketL2.sol
81: OrderInfo(address(this), order.trader, order.nonce, order.deadline), As per your comment
File: GammaTradeMarket.sol
function _verifyOrder(ResolvedOrder memory order) internal {
order.validate();
_permit2.permitWitnessTransferFrom(
order.toPermit(),
order.transferDetails(address(this)),
order.info.trader,
order.hash,
GammaOrderLib.PERMIT2_ORDER_TYPE,
order.sig
);
} When verifying the order, all the parameters are being obtained from File: GammaTradeMarket.sol
156: ResolvedOrder memory resolvedOrder = GammaOrderLib.resolve(gammaOrder, sig); The attacker only needs to change the File: GammaTradeMarketL2.sol
function modifyAutoHedgeAndClose(GammaModifyOrderL2 memory order, bytes memory sig) external {
GammaModifyInfo memory modifyInfo =
L2GammaDecoder.decodeGammaModifyInfo(order.param, order.lowerLimit, order.upperLimit, order.maximaDeviation);
uint64 pairId = userPositions[order.positionId].pairId;
_modifyAutoHedgeAndClose(
GammaOrder(
OrderInfo(address(this), order.trader, order.nonce, order.deadline), /// @note - trader's address will of that position's owner
pairId,
order.positionId,
_quoteTokenMap[pairId],
0,
0,
0,
0,
0,
0,
modifyInfo
),
sig
);
} Using |
Hey @Shubh0412, thank you for your contribution. We can observe here that the nonce is actively consumed at the Permit2 level, so a new signature would need to be generated and no replay can occur. |
Thank you @alex-ppg for making it clear. |
Lines of code
https://github.com/code-423n4/2024-05-predy/blob/main/src/markets/gamma/GammaTradeMarketL2.sol#L81
https://github.com/code-423n4/2024-05-predy/blob/main/src/markets/gamma/GammaTradeMarket.sol#L425
Vulnerability details
modifyAutoHedgeAndClose
function processes a trader's modify order to update auto close and auto hedge condition.Only the owner of that particular position should be able to modify.
However in the current state the function allows anyone to change/close a user's position.
Proof of Concept
_modifyAutoHedgeAndClose()
is called with the desired inputs & signature & after verifying the signature, the user's position is returned by calling the_getOrInitPosition()
.The above call leads to
_getOrInitPosition()
where inside theif
statement it is checked iftrader
calling the original modify function is the owner of that position.Scenario:
modifyAutoHedgeAndClose()
to change some of the settings.modifyAutoHedgeAndClose()
with the same signature Alice had used earlier to validate the transaction & withorder.trader
as Alice's address with manipulated inputs.userPosition
like the expiration, lower/upper limit, hedge interval, etc. which would result in loss to Alice's position in the market.Tools Used
Manual Review
Recommended Mitigation Steps
Use
msg.sender
instead oforder.trader
inside themodifyAutoHedgeAndClose()
function. This way when the call goes to_getOrInitPosition()
, since the caller is not the owner of the position, the call would revert.Assessed type
Invalid Validation
The text was updated successfully, but these errors were encountered: