eth: monitor malicious header retrieval requests

This commit is contained in:
Péter Szilágyi 2016-10-05 16:31:48 +03:00
parent a7cc3248fe
commit e482b5694f
2 changed files with 31 additions and 5 deletions

@ -17,6 +17,7 @@
package eth package eth
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"math" "math"
@ -371,14 +372,24 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
} }
case query.Origin.Hash != (common.Hash{}) && !query.Reverse: case query.Origin.Hash != (common.Hash{}) && !query.Reverse:
// Hash based traversal towards the leaf block // Hash based traversal towards the leaf block
if header := pm.blockchain.GetHeaderByNumber(origin.Number.Uint64() + query.Skip + 1); header != nil { var (
if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash { current = origin.Number.Uint64()
query.Origin.Hash = header.Hash() next = current + query.Skip + 1
)
if next <= current {
infos, _ := json.MarshalIndent(p.Peer.Info(), "", " ")
glog.V(logger.Warn).Infof("%v: GetBlockHeaders skip overflow attack (current %v, skip %v, next %v)\nMalicious peer infos: %s", p, current, query.Skip, next, infos)
unknown = true
} else {
if header := pm.blockchain.GetHeaderByNumber(next); header != nil {
if pm.blockchain.GetBlockHashesFromHash(header.Hash(), query.Skip+1)[query.Skip] == query.Origin.Hash {
query.Origin.Hash = header.Hash()
} else {
unknown = true
}
} else { } else {
unknown = true unknown = true
} }
} else {
unknown = true
} }
case query.Reverse: case query.Reverse:
// Number based traversal towards the genesis block // Number based traversal towards the genesis block

@ -17,6 +17,7 @@
package eth package eth
import ( import (
"math"
"math/big" "math/big"
"math/rand" "math/rand"
"testing" "testing"
@ -173,6 +174,20 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
pm.blockchain.GetBlockByNumber(0).Hash(), pm.blockchain.GetBlockByNumber(0).Hash(),
}, },
}, },
// Check a corner case where skipping overflow loops back into the chain start
{
&getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1},
[]common.Hash{
pm.blockchain.GetBlockByNumber(3).Hash(),
},
},
// Check a corner case where skipping overflow loops back to the same header
{
&getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64},
[]common.Hash{
pm.blockchain.GetBlockByNumber(1).Hash(),
},
},
// Check that non existing headers aren't returned // Check that non existing headers aren't returned
{ {
&getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},