Cosmos-sdk: Attacker validator can issue steak at AnteHandler

Created on 12 Nov 2018  ·  19Comments  ·  Source: cosmos/cosmos-sdk

Summary of Bug

In AnteHandler, FeeCollectionKeeper adds collected fees before saving signerAccs[0].
Attacker validator can send txs with fee and signerAccs[0] holding a false pubkey, ignoring the sig check error in CheckTx. Such txs will pass to DeliverTx, the FeeCollectionKeeper will collect fees, but these fees won't be charged from attacker's account due to sig check failure.

At gaia-9001 block 31998, we use this bug issue 150000 steaks.

@rigelrozanski


For Admin Use

  • [x] Not duplicate issue
  • [x] Appropriate labels applied
  • [ ] Appropriate contributors tagged
  • [ ] Contributor assigned/self-assigned
bug security

Most helpful comment

Thanks for sharing. @kauchy

And we want to give you 300Atom after mainnet launching.

kauchy3

Great work !

All 19 comments

You mean sending in invalid signature and checkTx ignores validating signatures?

yes @alexanderbez

it remains in unconfirmed txs in mempool and once the attacker propose, it get broadcasted @alexanderbez

Indeed! Good catch @kauchy!

gaia-9001 can not delegate now,because unbond pool is nearly negative😱

Excellent catch. Thanks @kauchy.

This is the most directly profitable exploit, but I think the underlying problem is more general - a proposer can cause partial state changes to be written from the ante handler even when the ante handler fails. Maybe we need to revert state changes when running the ante handler in DeliverTx (or equivalently, operate on a cached context). Alternatively, we could require that all state writes occur after checks in the ante handler, but that seems riskier and possibly less efficient in the non-Byzantine case.

gaia-9001 can not delegate now,because unbond pool is nearly negative😱

I confirm, we can't delegate anymore. Seems to affect all validators?

I confirm, we can't delegate anymore. Seems to affect all validators?

This sounds like a separate bug. What's the error?

This sounds like a separate bug. What's the error?

Same as what aurel posted:

ERROR: {"codespace":1,"code":1,"abci_code":65537,"message":"recovered: sanity check: loose tokens negative, pool: {-3898400000000 1254736300000000}
stack:
goroutine 94329 [running]:
runtime/debug.Stack(0xc440345878, 0xdcab00, 0xc42ad55fc0)
    /usr/local/go/src/runtime/debug/stack.go:24 +0xa7
github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runTx.func1(0xc440347b68, 0xc4403478f0, 0xc440347940)
    /root/.go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:612 +0xc8
panic(0xdcab00, 0xc42ad55fc0)
    /usr/local/go/src/runtime/panic.go:505 +0x229
github.com/cosmos/cosmos-sdk/x/stake/types.Pool.looseTokensToBonded(0xc431311000, 0xc431311060, 0xc431311120, 0x1158f20, 0xc430c2de40)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/types/pool.go:56 +0x2cc
github.com/cosmos/cosmos-sdk/x/stake/types.Validator.AddTokensFromDel(0xc423b5cc40, 0x14, 0x14, 0x1158f20, 0xc430c2de40, 0x200, 0xc42bd3c980, 0xc42bd3c9e0, 0xc428397cf0, 0x10, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/types/validator.go:392 +0x208
github.com/cosmos/cosmos-sdk/x/stake/keeper.Keeper.AddValidatorTokensAndShares(0x114f8e0, 0xc420216f90, 0x114f920, 0xc420216fa0, 0xc420253110, 0x115d6c0, 0xc4201e5d80, 0x115eda0, 0xc420906360, 0xc420253110, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/keeper/validator.go:132 +0x211
github.com/cosmos/cosmos-sdk/x/stake/keeper.Keeper.Delegate(0x114f8e0, 0xc420216f90, 0x114f920, 0xc420216fa0, 0xc420253110, 0x115d6c0, 0xc4201e5d80, 0x115eda0, 0xc420906360, 0xc420253110, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/keeper/delegation.go:399 +0x560
github.com/cosmos/cosmos-sdk/x/stake.handleMsgDelegate(0x1157a60, 0xc42b313b60, 0xc43491efc0, 0x10, 0xc423b5cb60, 0x14, 0x14, 0xc423b5cc40, 0x14, 0x14, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/handler.go:193 +0x400
github.com/cosmos/cosmos-sdk/x/stake.NewHandler.func1(0x1157a60, 0xc42b313b60, 0xc43491efc0, 0x10, 0x115a920, 0xc42dd74b90, 0x0, 0x0, 0x0, 0x0, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/x/stake/handler.go:22 +0x3b7
github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runMsgs(0xc420ae05a0, 0x1157a60, 0xc42b313b60, 0xc43491efc0, 0x10, 0xc42ad55340, 0x1, 0x1, 0xc43491ef02, 0x0, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:541 +0xbd6
github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runTx(0xc420ae05a0, 0x2, 0xc42b8f0820, 0xc2, 0xc2, 0x114dea0, 0xc4364a2ae0, 0x0, 0x0, 0x0, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:655 +0x3b9
github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).DeliverTx(0xc420ae05a0, 0xc42b8f0820, 0xc2, 0xc2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:476 +0x267
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/abci/client.(*localClient).DeliverTxAsync(0xc420b145a0, 0xc42b8f0820, 0xc2, 0xc2, 0x0)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/abci/client/local_client.go:76 +0x88
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/proxy.(*appConnConsensus).DeliverTxAsync(0xc420216b80, 0xc42b8f0820, 0xc2, 0xc2, 0xc42b3120f0)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/proxy/app_conn.go:73 +0x51
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state.execBlockOnProxyApp(0x11586e0, 0xc422071860, 0x115d360, 0xc420216b80, 0xc4233f01e0, 0xc42e9b3470, 0x1161e40, 0xc4201e2520, 0x3207, 0xc42f217740, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state/execution.go:248 +0x616
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state.(*BlockExecutor).ApplyBlock(0xc42208a310, 0x7, 0x0, 0xc42207cd10, 0x6, 0xc42207cd20, 0x9, 0x7e0e, 0x3207, 0xc42f217740, ...)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state/execution.go:96 +0x1a5
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).finalizeCommit(0xc42206e700, 0x7e0f)\

n   /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1327 +0xad9
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).tryFinalizeCommit(0xc42206e700, 0x7e0f)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1258 +0x462
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit.func1(0xc42206e700, 0x0, 0x7e0f)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1204 +0x98
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit(0xc42206e700, 0x7e0f, 0x0)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1235 +0x72c
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote(0xc42206e700, 0xc432c94780, 0xc4202996b0, 0x28, 0x42b5a9, 0x10cced8, 0x9)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1659 +0xc1e
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote(0xc42206e700, 0xc432c94780, 0xc4202996b0, 0x28, 0xb107c7, 0xc4239b40b0, 0xc440232b40)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1506 +0x59
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg(0xc42206e700, 0x114c580, 0xc43da93670, 0xc4202996b0, 0x28)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:660 +0x6af
github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine(0xc42206e700, 0x0)
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:617 +0x6a2
created by github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart
    /root/.go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:311 +0x140
"}

Same our end too:

ERROR: {"codespace":1,"code":1,"abci_code":65537,"message":"recovered: sanity check: loose tokens negative, pool: {-3998400000000 1254836300000000}\nstack:\ngoroutine 755 [running]:\nruntime/debug.Stack(0xc426dc9878, 0xdcaa40, 0xc4266681d0)\n\t/usr/local/go/src/runtime/debug/stack.go:24 +0xa7\ngithub.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runTx.func1(0xc426dcbb68, 0xc426dcb8f0, 0xc426dcb940)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:612 +0xc8\npanic(0xdcaa40, 0xc4266681d0)\n\t/usr/local/go/src/runtime/panic.go:505 +0x229\ngithub.com/cosmos/cosmos-sdk/x/stake/types.Pool.looseTokensToBonded(0xc427965700, 0xc427965760, 0xc427965840, 0x1158e60, 0xc421683e00)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/types/pool.go:56 +0x2cc\ngithub.com/cosmos/cosmos-sdk/x/stake/types.Validator.AddTokensFromDel(0xc422c47c40, 0x14, 0x14, 0x1158e60, 0xc421683e00, 0x200, 0xc425c7a280, 0xc425c7a2e0, 0xc425c34080, 0xb, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/types/validator.go:392 +0x208\ngithub.com/cosmos/cosmos-sdk/x/stake/keeper.Keeper.AddValidatorTokensAndShares(0x114f820, 0xc4201db140, 0x114f860, 0xc4201db150, 0xc4200de850, 0x115d600, 0xc4201e2ee0, 0x115ece0, 0xc4201b3320, 0xc4200de850, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/keeper/validator.go:132 +0x211\ngithub.com/cosmos/cosmos-sdk/x/stake/keeper.Keeper.Delegate(0x114f820, 0xc4201db140, 0x114f860, 0xc4201db150, 0xc4200de850, 0x115d600, 0xc4201e2ee0, 0x115ece0, 0xc4201b3320, 0xc4200de850, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/keeper/delegation.go:399 +0x560\ngithub.com/cosmos/cosmos-sdk/x/stake.handleMsgDelegate(0x11579a0, 0xc422f6d650, 0xc42492e080, 0x10, 0xc422c47c20, 0x14, 0x14, 0xc422c47c40, 0x14, 0x14, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/handler.go:193 +0x400\ngithub.com/cosmos/cosmos-sdk/x/stake.NewHandler.func1(0x11579a0, 0xc422f6d650, 0xc42492e080, 0x10, 0x115a860, 0xc4259ce690, 0x0, 0x0, 0x0, 0x0, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/x/stake/handler.go:22 +0x3b7\ngithub.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runMsgs(0xc420218960, 0x11579a0, 0xc422f6d650, 0xc42492e080, 0x10, 0xc424ad5580, 0x1, 0x1, 0xc42492e002, 0x0, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:541 +0xbd6\ngithub.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).runTx(0xc420218960, 0x2, 0xc423a11e10, 0xc2, 0xc2, 0x114dde0, 0xc424e88360, 0x0, 0x0, 0x0, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:655 +0x3b9\ngithub.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).DeliverTx(0xc420218960, 0xc423a11e10, 0xc2, 0xc2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/baseapp/baseapp.go:476 +0x267\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/abci/client.(*localClient).DeliverTxAsync(0xc420088d80, 0xc423a11e10, 0xc2, 0xc2, 0x0)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/abci/client/local_client.go:76 +0x88\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/proxy.(*appConnConsensus).DeliverTxAsync(0xc420222b00, 0xc423a11e10, 0xc2, 0xc2, 0x7)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/proxy/app_conn.go:73 +0x51\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state.execBlockOnProxyApp(0x1158620, 0xc420881fa0, 0x115d2a0, 0xc420222b00, 0xc4211da1e0, 0xc42141f8c0, 0x1161d80, 0xc42000e490, 0x32e4, 0xc424984140, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state/execution.go:248 +0x616\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state.(*BlockExecutor).ApplyBlock(0xc42010fd50, 0x7, 0x0, 0xc420c087b6, 0x6, 0xc420c087d0, 0x9, 0x7ea9, 0x32e4, 0xc424984140, ...)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/state/execution.go:96 +0x1a5\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).finalizeCommit(0xc4200bf880, 0x7eaa)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1327 +0xad9\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).tryFinalizeCommit(0xc4200bf880, 0x7eaa)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1258 +0x462\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit.func1(0xc4200bf880, 0x0, 0x7eaa)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1204 +0x98\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).enterCommit(0xc4200bf880, 0x7eaa, 0x0)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1235 +0x72c\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).addVote(0xc4200bf880, 0xc4241e7c20, 0xc424eba840, 0x28, 0x42b4d9, 0x10cce18, 0x109)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1659 +0xc1e\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).tryAddVote(0xc4200bf880, 0xc4241e7c20, 0xc424eba840, 0x28, 0xb106f7, 0xc421a02000, 0xc4214585a0)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:1506 +0x59\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).handleMsg(0xc4200bf880, 0x114c4c0, 0xc4230e6898, 0xc424eba840, 0x28)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:660 +0x6af\ngithub.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).receiveRoutine(0xc4200bf880, 0x0)\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:617 +0x6a2\ncreated by github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus.(*ConsensusState).OnStart\n\t/root/go/src/github.com/cosmos/cosmos-sdk/vendor/github.com/tendermint/tendermint/consensus/state.go:311 +0x140\n"}

Thanks @kauchy!! good job sir!

the issue steak do not add by lossen pool,but can delegate,this made lossen nearly 0,so no one can delegate now @cwgoes

@gamarin2 OK - that's presumably happening since tokens were minted without being deducted but the pool tracking total supply wasn't updated (since the tokens never should have been minted).

awesome, thanks for discovering and sharing.

thanks for sharing before GoS begins!

Thanks for sharing. @kauchy

And we want to give you 300Atom after mainnet launching.

kauchy3

Great work !

Amazing! Right before GoS 👏

Thanks for sharing. @kauchy

And we want to give you 300Atom after mainnet launching.

kauchy3

Great work !

Also add 200 Atoms from me !

@wansYoon @awrelll
If your reward is still effective.Please send the Atoms to cosmos1hcj3ze7ju4rll52qrc9260nl2rqv9jwqtzw7l0

Was this page helpful?
0 / 5 - 0 ratings