Open c4-bot-6 opened 2 months ago
The report is of sufficient quality
3docSec marked the issue as satisfactory
3docSec marked the issue as selected for report
Confirming as Med. There is the concrete possibility of fund loss, however, the onlyRole(OPERATOR_ROLE)
privilege required to exploit it mitigates the risk.
3docSec marked the issue as primary issue
@3docSec Since the Operator is a trusted role, and only the Operator can replay the the signature, is the risk not to be considered completely mitigated (at least at the Med level)?
Hey @d3e4 ,
Thank you for your comment.
However, we definitely submitted a broader issue in terms of securing off-chain components. So the view that you brought in your comment is only a possibility but does not represent the main issue of securing automated executions as stated in our submission.
Please consider all the cases we brought up: both purposeful and unintentional.
Hi @d3e4 yes the operator's trusted role has been considered for judging. If it wasn't for it, I certainly would've upgraded it to High.
I opted to keep it as M because relying on off-chain security (the operator's private keys storage & its software correctness) to secure the user's funds from misuse of their own signature is not something a user would normally expect, and goes fundamentally against what is in commonsense expected from signed messages in the first place: "I am signing X for you, and the contract ensures that X is all you can do with my signature".
Lines of code
https://github.com/code-423n4/2024-06-krystal-defi/blob/f65b381b258290653fa638019a5a134c4ef90ba8/src/V3Automation.sol#L79-L81 https://github.com/code-423n4/2024-06-krystal-defi/blob/f65b381b258290653fa638019a5a134c4ef90ba8/src/StructHash.sol#L274-L296
Vulnerability details
Impact
User signed orders can be replayed
Proof of Concept
All orders managed by the Krystal team are signed by the user, executed by the operator and the signature is verified on-chain:
However, there is no nonce field in the StructHash.Order. That means that the same hashed order can be reused multiple times. What's also important is that the order is used only to verify if it was signed by the user, however it's not checked if the order that user signed is the same as the params passed by the operator, because ExecuteParams sent to
V3Automation.execute()
use other set of params to indicate the action to perform:And later in the function,
params.userOrder
is not used, only the params prepared by the operator:Actually, this behavior is shown in test/integration/V3Automation.t.sol:
In the test above,
emptyUserConfig
- being really empty, i.e. consisting of only 0s, because it's not being set - is being signed and the order successfully executes, even though the action adds liquidity. That means that thedeadline
,liquidity
to get,recipient
of the funds,amount
, etc. - basically all parameters that the user signs are independent from what is being sent on-chain.To summarize, there are multiple occasions, where no nonce and actually no verification of execute params conformity to under signed order can be exploited:
Tools Used
Manual Review
Recommended Mitigation Steps
Introduce nonce and verification that operator parameters are the same that the user signed.
Assessed type
Other