mirror of https://github.com/nucypher/nucypher.git
Fix DoS vector on nodes through map storage
parent
94b489aa77
commit
c965f72c2e
|
@ -565,7 +565,7 @@ class Bob(Character):
|
|||
|
||||
# Ugh stupid federated only mode....
|
||||
if not self.federated_only:
|
||||
map_identifier = _hrac.hex()
|
||||
map_identifier = _hrac[:16].hex()
|
||||
else:
|
||||
map_identifier = map_id
|
||||
treasure_map = self.get_treasure_map_from_known_ursulas(self.network_middleware,
|
||||
|
|
|
@ -209,10 +209,10 @@ class Amonia(Alice):
|
|||
to the Policy for which I paid.
|
||||
"""
|
||||
# Here's the proper map associated with the policy for which I paid.
|
||||
map = policy.treasure_map
|
||||
the_map = policy.treasure_map
|
||||
|
||||
# I'll make a copy of it to modify for use in this attack.
|
||||
like_a_map_but_awful = SignedTreasureMap.from_bytes(bytes(map))
|
||||
like_a_map_but_awful = SignedTreasureMap.from_bytes(bytes(the_map))
|
||||
|
||||
# I'll split the film up into segments, because I know Ursula checks that the file size is under 50k.
|
||||
for i in range(50):
|
||||
|
@ -227,7 +227,7 @@ class Amonia(Alice):
|
|||
#############################################################################################
|
||||
# Now I'll mess with the hrac just a bit. I can't touch the last 16 bytes, because these #
|
||||
# are checked against the blockchain. But the first half is up for grabs. #
|
||||
bad_hrac = map._hrac[:28] + int(i).to_bytes(length=4, byteorder="big") #
|
||||
bad_hrac = the_map._hrac[:28] + int(i).to_bytes(length=4, byteorder="big") #
|
||||
# Note: if the hrac is reduced in length to 16 bytes, I'll be unable to perform this attack.#
|
||||
#############################################################################################
|
||||
|
||||
|
@ -244,5 +244,4 @@ class Amonia(Alice):
|
|||
like_a_map_but_awful.include_blockchain_signature(blockchain_signer=transacting_power.sign_message)
|
||||
|
||||
# Sucker.
|
||||
self.network_middleware.put_treasure_map_on_node(sucker_ursula, map_id=like_a_map_but_awful.public_id(),
|
||||
map_payload=bytes(like_a_map_but_awful))
|
||||
self.network_middleware.put_treasure_map_on_node(sucker_ursula, map_payload=bytes(like_a_map_but_awful))
|
||||
|
|
|
@ -373,7 +373,8 @@ def _make_rest_app(datastore: Datastore, this_node, serving_domain: str, log: Lo
|
|||
# Additionally, we determine the map identifier from the type of node.
|
||||
# If the node is federated, we also set the expiration for a week.
|
||||
if not this_node.federated_only:
|
||||
map_identifier = received_treasure_map._hrac.hex()
|
||||
# HOT LAVA - Do not forget to truncate the hrac to 16 bytes so it matches on-chain data.
|
||||
map_identifier = received_treasure_map._hrac[:16].hex()
|
||||
else:
|
||||
map_identifier = received_treasure_map.public_id()
|
||||
expiration_date = MayaDT.from_datetime(datetime.utcnow() + timedelta(days=7))
|
||||
|
@ -392,8 +393,8 @@ def _make_rest_app(datastore: Datastore, this_node, serving_domain: str, log: Lo
|
|||
# We also set the expiration from the data on the blockchain here.
|
||||
if not this_node.federated_only:
|
||||
policy_data, alice_checksum_address = this_node.policy_agent.fetch_policy(
|
||||
received_treasure_map._hrac[:16],
|
||||
with_owner=True)
|
||||
received_treasure_map._hrac[:16],
|
||||
with_owner=True)
|
||||
|
||||
# Check that this treasure map is from Alice per the Policy.
|
||||
if not received_treasure_map.verify_blockchain_signature(checksum_address=alice_checksum_address):
|
||||
|
|
|
@ -116,8 +116,7 @@ class TreasureMap:
|
|||
|
||||
self.message_kit, _signature_for_bob = encrypt_and_sign(bob_encrypting_key,
|
||||
plaintext=plaintext,
|
||||
signer=alice_stamp,
|
||||
)
|
||||
signer=alice_stamp)
|
||||
"""
|
||||
Here's our "hashed resource access code".
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ def test_alice_sets_treasure_map_decentralized(enacted_blockchain_policy):
|
|||
Same as test_alice_sets_treasure_map except with a blockchain policy.
|
||||
"""
|
||||
enacted_blockchain_policy.publish_treasure_map(network_middleware=MockRestMiddleware())
|
||||
treasure_map_hrac = enacted_blockchain_policy.treasure_map._hrac.hex()
|
||||
treasure_map_hrac = enacted_blockchain_policy.treasure_map._hrac[:16].hex()
|
||||
found = 0
|
||||
for node in enacted_blockchain_policy.bob.matching_nodes_among(enacted_blockchain_policy.alice.known_nodes):
|
||||
with node.datastore.describe(DatastoreTreasureMap, treasure_map_hrac) as treasure_map_on_node:
|
||||
|
|
|
@ -20,7 +20,7 @@ import maya
|
|||
import pytest
|
||||
|
||||
from nucypher.characters.unlawful import Amonia
|
||||
from nucypher.datastore.models import PolicyArrangement
|
||||
from nucypher.datastore.models import PolicyArrangement, TreasureMap as DatastoreTreasureMap
|
||||
from nucypher.datastore.datastore import RecordNotFound
|
||||
|
||||
|
||||
|
@ -145,14 +145,15 @@ def test_put_additional_treasure_map_on_network(blockchain_ursulas, blockchain_a
|
|||
label = b"this_is_the_path_to_which_access_is_being_granted"
|
||||
|
||||
policy = amonia.grant(bob=blockchain_bob,
|
||||
label=label,
|
||||
m=2,
|
||||
n=n,
|
||||
rate=int(1e18), # one ether
|
||||
expiration=policy_end_datetime)
|
||||
label=label,
|
||||
m=2,
|
||||
n=n,
|
||||
rate=int(1e18), # one ether
|
||||
expiration=policy_end_datetime)
|
||||
sucker = blockchain_ursulas[0]
|
||||
|
||||
amonia.use_ursula_as_an_involuntary_and_unbeknownst_cdn(policy, sucker_ursula=blockchain_ursulas[0])
|
||||
|
||||
# This assertion will fail if my attack succeeded.
|
||||
assert len(sucker.treasure_maps) <= 1
|
||||
with sucker.datastore.query_by(DatastoreTreasureMap) as all_treasure_maps:
|
||||
assert len(all_treasure_maps) <= 1
|
||||
|
|
|
@ -57,8 +57,8 @@ def test_bob_already_knows_all_nodes_in_treasure_map(enacted_federated_policy, f
|
|||
federated_bob.remember_node(ursula)
|
||||
|
||||
# Now, Bob can get the TreasureMap all by himself, and doesn't need a side channel.
|
||||
map = federated_bob.get_treasure_map(federated_alice.stamp, enacted_federated_policy.label)
|
||||
unknown, known = federated_bob.peek_at_treasure_map(treasure_map=map)
|
||||
the_map = federated_bob.get_treasure_map(federated_alice.stamp, enacted_federated_policy.label)
|
||||
unknown, known = federated_bob.peek_at_treasure_map(treasure_map=the_map)
|
||||
|
||||
# He finds that he didn't need to discover any new nodes...
|
||||
assert len(unknown) == 0
|
||||
|
|
Loading…
Reference in New Issue