Skip to content
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

[pfm][fix] patch arbitrary account passthrough #71

Merged
merged 11 commits into from
Aug 2, 2023

Conversation

agouin
Copy link
Member

@agouin agouin commented Jul 25, 2023

https://twitter.com/SCVSecurity/status/1682329758020022272

To ensure that users cannot pass funds through arbitrary accounts on intermediate chains, use hash of pfm+sender+channel.

e2e test: strangelove-ventures/interchaintest#678

@javiersuweijie
Copy link

Hey @agouin, a PR has been made that performed the same fix: #72. Would greatly appreciate to use that instead since the tests have been fixed.

The PR also handles some edge cases when dealing with fee processing during retries.

@agouin
Copy link
Member Author

agouin commented Jul 26, 2023

Hey @javiersuweijie thanks for your PR. I did not see the prior #69 that used the module account before starting this, my apologies. I put this up as a draft so that I could test it in the interchaintest packet forward test . I left some comments on your PR, but I think the code changes should look more like what's here in this PR.

@agouin agouin marked this pull request as ready for review July 26, 2023 18:12
// the receiver address is deterministic and can be used to identify the sender on the
// initial chain.
func getReceiver(channel string, originalSender string) (string, error) {
senderStr := fmt.Sprintf("%s/%s", channel, originalSender)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also use the port here? (in case this is used to wrap a port other than transfer in the future)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this makes sense to me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary, since PFM is ICS-20 middleware. Also, channels are on top of a port in IBC, so in the case this was modified in the future to support non-transfer packets, the channel ID would still give us enough to cover the channel+port. https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel

Copy link
Member

@jtieri jtieri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @nicolaslara that adding the port to the hash for the overridden receiver could future proof this.

Otherwise this lgtm. The only other change I would suggest is making note of the new behavior somewhere in the readme since this is somewhat of a substantial change to how the PFM works.

// the receiver address is deterministic and can be used to identify the sender on the
// initial chain.
func getReceiver(channel string, originalSender string) (string, error) {
senderStr := fmt.Sprintf("%s/%s", channel, originalSender)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this makes sense to me

override packet

fix incorrect bech32

update error desc

refactor receiveFunds
@agouin
Copy link
Member Author

agouin commented Jul 29, 2023

README has been updated to explain the intermediate receiver behavior and recommended usage of the packet receiver field, since we can use this fix as a feature to detect PFM on intermediate chains.

@jtieri jtieri added BACKPORT Backport into maintained branches packet-forward-middleware Label for items related to the packet forward middleware labels Aug 2, 2023
@jtieri jtieri merged commit d72e83c into main Aug 2, 2023
5 checks passed
@jtieri jtieri deleted the andrew/pfm_fix_arbitrary_passthrough branch August 2, 2023 21:10
@jtieri jtieri restored the andrew/pfm_fix_arbitrary_passthrough branch August 2, 2023 21:11
mergify bot pushed a commit that referenced this pull request Aug 2, 2023
* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go
mergify bot pushed a commit that referenced this pull request Aug 2, 2023
* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go
mergify bot pushed a commit that referenced this pull request Aug 2, 2023
* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go
nicolaslara added a commit that referenced this pull request Aug 3, 2023
…ugh (#78)

* [pfm][fix] patch arbitrary account passthrough (#71)

* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go

* fix conflict

* fix merge

---------

Co-authored-by: Andrew Gouin <[email protected]>
Co-authored-by: Nicolas Lara <[email protected]>
jtieri added a commit that referenced this pull request Aug 3, 2023
…ugh (#79)

* [pfm][fix] patch arbitrary account passthrough (#71)

* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go

* fix merge

* chore: resolve conflicts

---------

Co-authored-by: Andrew Gouin <[email protected]>
Co-authored-by: Nicolas Lara <[email protected]>
Co-authored-by: jtieri <[email protected]>
jtieri added a commit that referenced this pull request Aug 3, 2023
…ugh (#80)

* [pfm][fix] patch arbitrary account passthrough (#71)

* don't allow funds to pass through arbitrary accounts, use hash of pfm+sender+channel

* lint

* use types.ModuleName

* update tests

* better errors

override packet

fix incorrect bech32

update error desc

refactor receiveFunds

* update README

* tidy errors

* lint

* chore: remove go.work

* chore: lint

---------

Co-authored-by: jtieri <[email protected]>
(cherry picked from commit d72e83c)

# Conflicts:
#	.gitignore
#	middleware/packet-forward-middleware/router/module_test.go
#	modules/ibc-hooks/client/cli/query.go
#	modules/ibc-hooks/hooks.go
#	modules/ibc-hooks/ibc_module.go
#	modules/ibc-hooks/ics4_middleware.go
#	modules/ibc-hooks/keeper/keeper.go
#	modules/ibc-hooks/sdkmodule.go
#	modules/ibc-hooks/simapp/ante.go
#	modules/ibc-hooks/simapp/app.go
#	modules/ibc-hooks/simapp/export.go
#	modules/ibc-hooks/simapp/simulation_test.go
#	modules/ibc-hooks/simapp/test_helpers.go
#	modules/ibc-hooks/tests/unit/mocks/isc4_middleware_mock.go
#	modules/ibc-hooks/tests/unit/module_test.go
#	modules/ibc-hooks/wasm_hook.go

* fix merge

* chore: resolve conflicts

---------

Co-authored-by: Andrew Gouin <[email protected]>
Co-authored-by: Nicolas Lara <[email protected]>
Co-authored-by: jtieri <[email protected]>
@agouin agouin deleted the andrew/pfm_fix_arbitrary_passthrough branch August 4, 2023 00:29
mergify bot pushed a commit to Stride-Labs/stride that referenced this pull request Jan 10, 2024
## Context
During liquid stake and forward, the autopilot "receiver" of the inbound transfer becomes the "sender" of the transfer back to the host. However, downstream applications shouldn't trust this new "sender" so we need to use a generated address instead. 

To be clear, using the original sender would not introduce an attack vector on Stride. However, it could introduce an attack vector on a different zone, _if_ they were to trust the sender. The hashed sender is used to make the assumption more explicit that new zones should not trust the address.

This bug appeared in PFM (if more context is needed):
* [Issue](cosmos/ibc-apps#68)
* [PR fix](cosmos/ibc-apps#71)

## Design Considerations
There wasn't an immediately obvious way to implement this. The complexity arises in that the address used for the inbound transfer doesn't always line up with the address used in the autopilot action. Additionally, if a bank send is required after the transfer (in the event that we transferred to an intermediate recipient), some scenarios would require us to build the IBC denom hash ourselves (not impossible, but adds a lot of unnecessary code).

There didn't seem to be a clean way to refactor the callback such that we use a different receiver based on the action type (i.e. use "hashed" for LS&Forward, but "original" for Claim). As such, I think the only two options were as follows: 

1. _Send inbound transfer to original receiver_
  * ✅  **Claim**: No changes
  * ✅  **Liquid Stake**: No changes
  * ❌  **Liquid Stake and Forward**: Requires us to bank send to hashed receiver (but this is straightforward since the token is not an IBC denom)
2. _Send inbound transfer to hashed receiver_
  * ❌❌ **Claim**: Would require a bank send to the original receiver (we'd need to copy over all the IBC hashing code from ibc-go in order to handle both native and non-native denoms)
  * ❌  **Liquid Stake**: Would require a bank send to the original receiver (but this is straightforward since the token is not an IBC denom)
  * ✅ **Liquid Stake and Forward**: No changes
3. _Decide recipient based on action_
  * ✅  **Claim**: No changes
  * ✅  **Liquid Stake**: No changes
  * ✅ **Claim:** No changes
  * ❌ Requires some somewhat sloppy refactoring since the change must be upstream of the transfer

~I do think using the hashed receiver address as the inbound recipient and actor for each of the autopilot actions, does feel slightly more correct. However, I don't think it's a significant enough argument to justify the additional changes that would be required. Additionally, going with option 1 demands no changes to the existing autopilot functions that have been live on mainnet.~

After discussing offline, we decided to do option 3 and to simplify the autopilot schema so the refactor isn't as messy. This gives us the benefit of not having to worry about doing an extra bank send, but also not duplicating code in multiple places (see [here](#1038 (comment))).

Option 3 is tracked in #1046 

## Brief Changelog
* Added `GenerateHashedAddress` to generate the hashed address from the channel Id a previous sender (body of function taken from PFM)
* Renamed `PacketForwardMetadata` to `AutopilotMetadata`
* Added a bank send to the hashed address in LS and forward
* Set the hashed address as the outbound sender during LS and forward
* Restricted packets to being either autopilot or PFM (but not both)
* Cleaned up the variable names to avoid confusion with all the data structures (open to better names though!)
* Moved structs out of parser.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BACKPORT Backport into maintained branches packet-forward-middleware Label for items related to the packet forward middleware
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants