commit: b15f8b06425edbfc3a7cef2a55c609b12ee14377
parent d1b053f3ba4170021c511b0d06a41405d3ab07d3
Author: Alex Gleason <alex@alexgleason.me>
Date: Wed, 23 Aug 2023 13:10:19 -0500
Prevent webfinger spoofing
Diffstat:
4 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex
@@ -216,10 +216,26 @@ defmodule Pleroma.Web.WebFinger do
_ ->
{:error, {:content_type, nil}}
end
+ |> case do
+ {:ok, data} -> validate_webfinger(address, data)
+ error -> error
+ end
else
error ->
Logger.debug("Couldn't finger #{account}: #{inspect(error)}")
error
end
end
+
+ defp validate_webfinger(url, %{"subject" => "acct:" <> acct} = data) do
+ with %URI{host: request_host} <- URI.parse(url),
+ [_name, acct_host] <- String.split(acct, "@"),
+ {_, true} <- {:hosts_match, acct_host == request_host} do
+ {:ok, data}
+ else
+ _ -> {:error, {:webfinger_invalid, url, data}}
+ end
+ end
+
+ defp validate_webfinger(url, data), do: {:error, {:webfinger_invalid, url, data}}
end
diff --git a/test/fixtures/tesla_mock/gleasonator.com_host_meta b/test/fixtures/tesla_mock/gleasonator.com_host_meta
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
+ <Link rel="lrdd" template="https://gleasonator.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
+</XRD>
+\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/webfinger_spoof.json b/test/fixtures/tesla_mock/webfinger_spoof.json
@@ -0,0 +1,28 @@
+{
+ "aliases": [
+ "https://gleasonator.com/users/alex",
+ "https://mitra.social/users/alex"
+ ],
+ "links": [
+ {
+ "href": "https://gleasonator.com/users/alex",
+ "rel": "http://webfinger.net/rel/profile-page",
+ "type": "text/html"
+ },
+ {
+ "href": "https://gleasonator.com/users/alex",
+ "rel": "self",
+ "type": "application/activity+json"
+ },
+ {
+ "href": "https://gleasonator.com/users/alex",
+ "rel": "self",
+ "type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
+ },
+ {
+ "rel": "http://ostatus.org/schema/1.0/subscribe",
+ "template": "https://gleasonator.com/ostatus_subscribe?acct={uri}"
+ }
+ ],
+ "subject": "acct:trump@whitehouse.gov"
+}
diff --git a/test/pleroma/web/web_finger_test.exs b/test/pleroma/web/web_finger_test.exs
@@ -76,15 +76,6 @@ defmodule Pleroma.Web.WebFingerTest do
{:ok, _data} = WebFinger.finger(user)
end
- test "returns the ActivityPub actor URI and subscribe address for an ActivityPub user with the ld+json mimetype" do
- user = "kaniini@gerzilla.de"
-
- {:ok, data} = WebFinger.finger(user)
-
- assert data["ap_id"] == "https://gerzilla.de/channel/kaniini"
- assert data["subscribe_address"] == "https://gerzilla.de/follow?f=&url={uri}"
- end
-
test "it work for AP-only user" do
user = "kpherox@mstdn.jp"
@@ -99,12 +90,6 @@ defmodule Pleroma.Web.WebFingerTest do
assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}"
end
- test "it works for friendica" do
- user = "lain@squeet.me"
-
- {:ok, _data} = WebFinger.finger(user)
- end
-
test "it gets the xrd endpoint" do
{:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la")
@@ -203,6 +188,29 @@ defmodule Pleroma.Web.WebFingerTest do
assert :error = WebFinger.finger("pekorino@pawoo.net")
end
+
+ test "prevents spoofing" do
+ Tesla.Mock.mock(fn
+ %{
+ url: "https://gleasonator.com/.well-known/webfinger?resource=acct:alex@gleasonator.com"
+ } ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/webfinger_spoof.json"),
+ headers: [{"content-type", "application/jrd+json"}]
+ }}
+
+ %{url: "https://gleasonator.com/.well-known/host-meta"} ->
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/gleasonator.com_host_meta")
+ }}
+ end)
+
+ {:error, _data} = WebFinger.finger("alex@gleasonator.com")
+ end
end
test "prevents forgeries" do