def _check(self, context: Context) -> None: if context.node_type == NodeType.GETH: payload = self.get_rpc_json(context.target, method="admin_addPeer", params=[self.test_enode]) if payload: context.report.add_issue( Issue( title="Peer list manipulation", description= "Arbitrary peers can be added using the admin_addPeer RPC call.", raw_data=payload, severity=Severity.HIGH, )) elif context.node_type == NodeType.PARITY: payload = self.get_rpc_json( context.target, method="parity_addReservedPeer", params=[self.test_enode], ) if payload: context.report.add_issue( Issue( title="Peer list manipulation", description= "Reserved peers can be added to the node's peer list using the parity_addReservedPeer RPC call", raw_data=payload, severity=Severity.HIGH, ))
def _check(self, context: Context) -> None: client_version = self.get_rpc_json(context.target, "web3_clientVersion") context.report.add_issue( Issue( title=self.__class__.__name__, description="The node surfaces it's version information", raw_data=client_version, severity=Severity.NONE, )) try: client_semver = re.findall(SEMVER_REGEX, client_version)[0] except IndexError: raise PluginException( f"Could not extract the client version from string {client_version}" ) if context.node_type == NodeType.GETH: node_semver = self.latest_repo_release(self.geth_url) elif context.node_type == NodeType.PARITY: node_semver = self.latest_repo_release(self.parity_url) else: raise PluginException( f"No repo known for node type {context.node_type}") if client_semver != node_semver: context.report.add_issue( Issue( title="Node version out of date", description=f"{client_semver} != {node_semver}", raw_data=client_version, severity=Severity.HIGH, ))
def _check(self, context: Context) -> None: if context.node_type == NodeType.GETH: payload = self.get_rpc_json(context.target, method="txpool_content") context.report.add_issue( Issue( title="TxPool Content", description=( "Anyone can see the transcation pool contents " "using the txpool_content RPC call."), raw_data=payload, severity=Severity.LOW, )) elif context.node_type == NodeType.PARITY: payload = self.get_rpc_json(context.target, method="parity_pendingTransactions") context.report.add_issue( Issue( title="TxPool Content", description=( "Anyone can see the transaction pool contents " "using the parity_pendingTransactions RPC call."), raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: node_syncing = self.get_rpc_json(context.target, "eth_syncing") node_blocknum = int(self.get_rpc_json(context.target, "eth_blockNumber"), 16) net_blocknum = self.get_rpc_int(self.infura_url, "eth_blockNumber") if node_blocknum < (net_blocknum - self.block_threshold) and not node_syncing: context.report.add_issue( Issue( title="Synchronization Status", description=( "The node's block number is stale and " "its not synchronizing. The node is stuck!" ), raw_data=node_syncing, severity=Severity.CRITICAL, ) ) else: context.report.add_issue( Issue( title="Synchronization Status", description=f"Syncing: {node_syncing} Block Number: {node_blocknum}", raw_data=node_syncing, severity=Severity.NONE, ) )
def _check(self, context: Context) -> None: payload = self.get_rpc_json(context.target, method="admin_stopRPC") context.report.add_issue( Issue( title="Admin RPC Stop Rights", description= "The HTTP RPC service can be stopped using the admin_stopRPC RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: payload = self.get_rpc_json(context.target, method="admin_startWS") context.report.add_issue( Issue( title="Admin Websocket Start Rights", description= "The RPC Websocket service can be started using the admin_startWS RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: payload = self.get_rpc_json(context.target, method="txpool_status") context.report.add_issue( Issue( title="TxPool Status", description= "Anyone can see the transaction pool status using the txpool_status RPC call.", raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.GETH: return payload = self.get_rpc_json(context.target, method="txpool_status") context.report.add_issue( Issue( title="TxPool Status", description=("Anyone can see the transaction pool status " "using the txpool_status RPC call."), raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: payload = self.get_rpc_json(context.target, method="parity_dropNonReservedPeers") if payload: context.report.add_issue( Issue( title="Peer list manipulation", description= "Anyone can drop the non-reserved peerlist on the node using the " "parity_dropNonReservedPeers RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: sha_hash = self.get_rpc_json(target=context.target, method="web3_sha3", params=[self.test_input]) if sha_hash != self.test_output: context.report.add_issue( Issue( title="SHA3 test failed", description= f"Expected {self.test_output} but received {sha_hash}", raw_data=sha_hash, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json(context.target, method="parity_pendingTransactionsStats") context.report.add_issue( Issue( title="TxPool Statistics", description= "Anyone can see the transaction pool statistics using the parity_pendingTransactionsStats RPC call.", raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: accounts = self.get_rpc_json(context.target, "eth_accounts") for account in accounts: balance = self.get_rpc_int(self.infura_url, method="eth_getBalance", params=[account, "latest"]) context.report.add_issue( Issue( title="Found account", description=f"Account: {account} Balance: {balance}", raw_data=account, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.GETH: return payload = self.get_rpc_json(context.target, method="admin_nodeInfo") context.report.add_issue( Issue( title="Admin Node Info Leaks", description= "Admin-only information can be fetched using the admin_nodeInfo RPC call.", raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: mining_status = self.get_rpc_json(context.target, "eth_mining") if self.should_mine is not None and mining_status != self.should_mine: context.report.add_issue( Issue( title="Mining Status", description=("The node should be mining but isn't" if self.should_mine else "The node should not be mining but is"), raw_data=mining_status, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: node_listening = self.get_rpc_json(context.target, "net_listening") # SCAN[HIGH]: Node not listening to peers if not node_listening: context.report.add_issue( Issue( title="Node not listening to peers", description= "The node is not listening to new peer requests", raw_data=node_listening, severity=Severity.HIGH, ))
def _check(self, context: Context) -> None: current_hashrate = int( self.get_rpc_json(context.target, "eth_hashrate"), 16) if current_hashrate < self.expected_hashrate: context.report.add_issue( Issue( title="Mining Hashrate Low", description= f"The hashrate should be >= {self.expected_hashrate} but only is {current_hashrate}", raw_data=current_hashrate, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json(context.target, method="parity_devLogs") context.report.add_issue( Issue( title="Developer log information leak", description= "The node's developer logs can be fetched using the parity_devLogs RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: current_peercount = int( self.get_rpc_json(context.target, "net_peerCount"), 16) if self.minimum_peercount > current_peercount: context.report.add_issue( Issue( title="Number of peers too low!", description= f"Too few peers (current < minimum): {current_peercount} < {self.minimum_peercount}", raw_data=current_peercount, severity=Severity.MEDIUM, ))
def _check(self, context: Context): if context.node_type != NodeType.GETH: return payload = self.get_rpc_json(context.target, method="admin_datadir") context.report.add_issue( Issue( title="Admin datadir access", description= "The datadir directory path can be fetched using the admin_datadir RPC call.", raw_data=payload, severity=Severity.LOW, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.GETH: return payload = self.get_rpc_json(context.target, method="admin_stopWS") if payload: context.report.add_issue( Issue( title="Admin Websocket Stop Rights", description= "The RPC Websocket service can be stopped using the admin_stopWS RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: if context.node_type == NodeType.PARITY: payload = self.get_rpc_json(context.target, method="parity_netPeers") context.report.add_issue( Issue( title="Peer list information leak", description= "Admin-only peer list information can be fetched with the parity_netPeers RPC call.", raw_data=payload, severity=Severity.MEDIUM, )) elif context.node_type == NodeType.GETH: payload = self.get_rpc_json(context.target, method="admin_peers") context.report.add_issue( Issue( title="Admin Peerlist Access", description= "Admin-only information about the peer list can be fetched using the admin_peers RPC " "call.", raw_data=payload, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json(context.target, method="parity_upgradeReady") context.report.add_issue( Issue( title="The node can be upgraded", description=("A new node upgrade has been detected using " "the parity_upgradeReady RPC call."), raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context): payload = self.get_rpc_json( target=context.target, method="personal_newAccount", params=[self.test_password], ) context.report.add_issue( Issue( title="We managed to create a new account on your node", description=("A new account can be generated on the node " "itself using the personal_newAccount RPC call."), raw_data=payload, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json(context.target, method="parity_setMode", params=[self.mode]) context.report.add_issue( Issue( title="The sync mode can be changed", description= "Anyone can change the node's sync mode using the parity_setMode RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json(context.target, method="parity_setGasFloorTarget", params=[self.gas_floor]) context.report.add_issue( Issue( title="Gas floor target can be changed", description=("Anyone can change the gas floor value using " "the parity_setGasFloorTarget RPC call."), raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json( context.target, method="parity_setMinGasPrice", params=[self.gas_price] ) if payload: context.report.add_issue( Issue( title="Transaction minimum gas can be changed", description="Anyone can change the minimum transaction gas limit using the parity_setMinGasPrice RPC call.", raw_data=payload, severity=Severity.CRITICAL, ) )
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json( context.target, method="parity_setChain", params=[self.target_chain], ) context.report.add_issue( Issue( title="Chain preset change possible", description= "Anyone can change the node's target chain value using the parity_setChain RPC call.", raw_data=payload, severity=Severity.CRITICAL, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.GETH: return payload = self.get_rpc_json(context.target, method="admin_startRPC") if payload: context.report.add_issue( Issue( title="Admin RPC Start Rights", description=( "The HTTP RPC service can be started " "using the admin_startRPC RPC call." ), raw_data=payload, severity=Severity.CRITICAL, ) )
def _check(self, context: "Context"): if context.node_type != NodeType.GETH: return payload = self.get_rpc_json( target=context.target, method="personal_importRawKey", params=[self.keydata, self.password], ) context.report.add_issue( Issue( title="We managed to import an account on your node", description= "A private key can be imported on the node to initialize an account using the " "personal_importRawKey RPC call.", raw_data=payload, severity=Severity.MEDIUM, ))
def _check(self, context: Context) -> None: if context.node_type != NodeType.PARITY: return payload = self.get_rpc_json( context.target, method="parity_setExtraData", params=[self.extra_data], ) context.report.add_issue( Issue( title="Extra data change possible", description= "Anyone can change the extra data attached to newly mined blocks using the " "parity_setExtraData RPC call.", raw_data=payload, severity=Severity.LOW, ))