From 6d715b770298efcc1fb213c15d77e662e81a8843 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 14 Jul 2019 17:47:08 +0000 Subject: [PATCH] security: detect object containment violations at the IR level It is more efficient to check for object containment violations at the IR level instead of in the protocol handlers. OStatus containment is especially a tricky situation, as the containment rules don't match those of IR and ActivityPub. Accordingly, we just always do a final containment check at the IR level before the object is added to the IR object graph. --- lib/pleroma/object/containment.ex | 8 ++++++ lib/pleroma/web/activity_pub/activity_pub.ex | 2 ++ test/object/containment_test.exs | 30 ++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/lib/pleroma/object/containment.ex b/lib/pleroma/object/containment.ex index ada9da0bb..f077a9f32 100644 --- a/lib/pleroma/object/containment.ex +++ b/lib/pleroma/object/containment.ex @@ -48,6 +48,9 @@ defmodule Pleroma.Object.Containment do end end + def contain_origin(id, %{"attributedTo" => actor} = params), + do: contain_origin(id, Map.put(params, "actor", actor)) + def contain_origin_from_id(_id, %{"id" => nil}), do: :error def contain_origin_from_id(id, %{"id" => other_id} = _params) do @@ -60,4 +63,9 @@ defmodule Pleroma.Object.Containment do :error end end + + def contain_child(%{"object" => %{"id" => id, "attributedTo" => _} = object}), + do: contain_origin(id, object) + + def contain_child(_), do: :ok end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 55315d66e..fd5521c98 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.Conversation alias Pleroma.Notification alias Pleroma.Object + alias Pleroma.Object.Containment alias Pleroma.Object.Fetcher alias Pleroma.Pagination alias Pleroma.Repo @@ -126,6 +127,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, map} <- MRF.filter(map), {recipients, _, _} = get_recipients(map), {:fake, false, map, recipients} <- {:fake, fake, map, recipients}, + :ok <- Containment.contain_child(map), {:ok, map, object} <- insert_full_object(map) do {:ok, activity} = Repo.insert(%Activity{ diff --git a/test/object/containment_test.exs b/test/object/containment_test.exs index a860355b8..455415fcd 100644 --- a/test/object/containment_test.exs +++ b/test/object/containment_test.exs @@ -64,4 +64,34 @@ defmodule Pleroma.Object.ContainmentTest do "[error] Could not decode user at fetch https://n1u.moe/users/rye, {:error, :error}" end end + + describe "containment of children" do + test "contain_child() catches spoofing attempts" do + data = %{ + "id" => "http://example.com/whatever", + "type" => "Create", + "object" => %{ + "id" => "http://example.net/~alyssa/activities/1234", + "attributedTo" => "http://example.org/~alyssa" + }, + "actor" => "http://example.com/~bob" + } + + :error = Containment.contain_child(data) + end + + test "contain_child() allows correct origins" do + data = %{ + "id" => "http://example.org/~alyssa/activities/5678", + "type" => "Create", + "object" => %{ + "id" => "http://example.org/~alyssa/activities/1234", + "attributedTo" => "http://example.org/~alyssa" + }, + "actor" => "http://example.org/~alyssa" + } + + :ok = Containment.contain_child(data) + end + end end