Prevent spoofing webfinger

This commit is contained in:
Alex Gleason 2024-05-22 19:08:37 +01:00 committed by Floatingghost
parent 4457928e32
commit a953b1d927
4 changed files with 73 additions and 15 deletions

View file

@ -217,10 +217,28 @@ def finger(account) do
_ -> _ ->
{:error, {:content_type, nil}} {:error, {:content_type, nil}}
end end
|> case do
{:ok, data} -> validate_webfinger(address, data)
error -> error
end
else else
error -> error ->
Logger.debug("Couldn't finger #{account}: #{inspect(error)}") Logger.debug("Couldn't finger #{account}: #{inspect(error)}")
error error
end end
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 end

View file

@ -0,0 +1,3 @@
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
<Link rel="lrdd" template="https://bad.com/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
</XRD>

View file

@ -0,0 +1,28 @@
{
"aliases": [
"https://bad.com/users/meanie",
"https://anotherbad.social/users/meanie"
],
"links": [
{
"href": "https://bad.com/users/meanie",
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html"
},
{
"href": "https://bad.com/users/meanie",
"rel": "self",
"type": "application/activity+json"
},
{
"href": "https://bad.com/users/meanie",
"rel": "self",
"type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://bad.com/ostatus_subscribe?acct={uri}"
}
],
"subject": "acct:oopsie@notwhereitshouldbe.org"
}

View file

@ -76,15 +76,6 @@ test "returns the ActivityPub actor URI for an ActivityPub user" do
{:ok, _data} = WebFinger.finger(user) {:ok, _data} = WebFinger.finger(user)
end 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 test "it work for AP-only user" do
user = "kpherox@mstdn.jp" user = "kpherox@mstdn.jp"
@ -99,12 +90,6 @@ test "it work for AP-only user" do
assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}" assert data["subscribe_address"] == "https://mstdn.jp/authorize_interaction?acct={uri}"
end end
test "it works for friendica" do
user = "lain@squeet.me"
{:ok, _data} = WebFinger.finger(user)
end
test "it gets the xrd endpoint" do test "it gets the xrd endpoint" do
{:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la") {:ok, template} = WebFinger.find_lrdd_template("social.heldscal.la")
@ -180,5 +165,29 @@ test "respects xml content-type" do
{:ok, _data} = WebFinger.finger("pekorino@pawoo.net") {:ok, _data} = WebFinger.finger("pekorino@pawoo.net")
end end
test "prevents spoofing" do
Tesla.Mock.mock(fn
%{
url: "https://bad.com/.well-known/webfinger?resource=acct:meanie@bad.com"
} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/webfinger_spoof.json"),
headers: [{"content-type", "application/jrd+json"}]
}}
%{url: "https://bad.com/.well-known/host-meta"} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/bad.com_host_meta")
}}
end)
{:error, _data} = WebFinger.finger("meanie@bad.com")
end
end end
end end