Potential Security Vulnerability Report — uDEFI with tez and tzBTC LB, uUSD with tzBTC Collateral
On April 28 the ubinetic developers noticed unexpected behaviour of some of the smart contracts during a manual test. Further inspection revealed a potential vulnerability. As a consequence, the vault engines for the uDEFI token with tez or tzBTC LB collateral and the uUSD token with tzBTC collateral had to be deactivated temporarily. They have now been re-deployed. No funds were directly at risk at any time during the incident.
The detailed postmortem:
Status: Complete, action items in progress
Summary: A SmartPy version migration has gone wrong, allowing internal entrypoints to be called externally.
Impact: All internal entrypoints could be called by an external address, effectively allowing someone performing the action in the name of the last user interacting with the contract. No funds were directly at risk at any time during the incident.
Root Causes: SmartPy deprecated
@sp.global_lambda in favour of a parametrized
@sp.private_lambda. During the migration to the new system our
verify_internal lambda was configured to use the parameter
verify_internal was only verifying whether the caller of the entrypoint was the contract itself and not “eventful” we could see the lambda in the transpiled Michelson but it was never called. Only
wrap_call=True will force the lambda even if not “eventful” to be computed at the defined point.
Trigger: A manual test routine has shown the unexpected behaviour.
Resolution: The engines have been removed from the list of admin disallowing them to mint and burn synthetic assets, as well as the ability to set a YOU weight. New engines with the fix (basically setting
wrap_call=True) have been deployed.
Detection: A user in discord complained about not being able to convert.
What went well
- As soon as the ubinetic team was made aware of the issue, the mitigation was implemented and deployed within less than 1 hour 30 minutes (including the multisig ceremony).
- The youves multisig parties understood the urgency and reacted on this unplanned issue within 5 minutes. (thank you!!!)
What went wrong
- Deployment testing protocol did not check the internal entrypoints.
Where we got lucky
- Unplanned manual test decided to also test the “internal” entrypoints.
set_target_pricechecks the sender.
- Also when it seems unnecessary the additional check in
set_target_pricemade sure that no unlimited amounts of synthetic assets could be minted.
- Manual test protocols are important and need to cover every entrypoint, also if the expected behaviour is a fail.
2022–04–28 (all times UTC)
- 11:40 manual test identifies weird behaviour
- 11:55 engines with behaviour listed in list
- 12:00 preparation of multisig execution payload
- 12:47 multisig ceremony is kicked-off
- 12:51 required signatures are collected
- 13:15 flawed youves engines removed from admin list (ooRPfrFBUdKBkxRoqDvJnu8zUxVywRtTkjQkXBpYbZs1vuwU69i)