From ba558c0c242fed48f0fec1cf7fe86642d07e410b Mon Sep 17 00:00:00 2001 From: Oneric Date: Thu, 7 Mar 2024 00:00:25 +0100 Subject: [PATCH] Limit instance emoji to image types Else malicious emoji packs or our EmojiStealer MRF can put payloads into the same domain as the instance itself. Sanitising the content type should prevent proper clients from acting on any potential payload. Note, this does not affect the default emoji shipped with Akkoma as they are handled by another plug. However, those are fully trusted and thus not in needed of sanitisation. --- lib/pleroma/web/plugs/instance_static.ex | 22 ++++++++++++++++++++-- lib/pleroma/web/plugs/uploaded_media.ex | 8 ++------ lib/pleroma/web/plugs/utils.ex | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 lib/pleroma/web/plugs/utils.ex diff --git a/lib/pleroma/web/plugs/instance_static.ex b/lib/pleroma/web/plugs/instance_static.ex index 5f9a6ee83..b72b604a1 100644 --- a/lib/pleroma/web/plugs/instance_static.ex +++ b/lib/pleroma/web/plugs/instance_static.ex @@ -3,8 +3,12 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.Plugs.InstanceStatic do + import Plug.Conn + require Pleroma.Constants + alias Pleroma.Web.Plugs.Utils + @moduledoc """ This is a shim to call `Plug.Static` but with runtime `from` configuration. @@ -43,11 +47,25 @@ def call(conn, _) do conn end - defp call_static(conn, opts, from) do + defp set_static_content_type(conn, "/emoji/" <> _ = request_path) do + real_mime = MIME.from_path(request_path) + safe_mime = Utils.get_safe_mime_type(%{allowed_mime_types: ["image"]}, real_mime) + + put_resp_header(conn, "content-type", safe_mime) + end + + defp set_static_content_type(conn, request_path) do + put_resp_header(conn, "content-type", MIME.from_path(request_path)) + end + + defp call_static(%{request_path: request_path} = conn, opts, from) do opts = opts |> Map.put(:from, from) + |> Map.put(:set_content_type, false) - Plug.Static.call(conn, opts) + conn + |> set_static_content_type(request_path) + |> Pleroma.Web.Plugs.StaticNoCT.call(opts) end end diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex index 9f13d919b..746203087 100644 --- a/lib/pleroma/web/plugs/uploaded_media.ex +++ b/lib/pleroma/web/plugs/uploaded_media.ex @@ -11,6 +11,7 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do require Logger alias Pleroma.Web.MediaProxy + alias Pleroma.Web.Plugs.Utils @behaviour Plug # no slashes @@ -76,14 +77,9 @@ defp media_is_banned(_, {:url, url}), do: MediaProxy.in_banned_urls(url) defp media_is_banned(_, _), do: false - defp get_safe_mime_type(%{allowed_mime_types: allowed_mime_types} = _opts, mime) do - [maintype | _] = String.split(mime, "/", parts: 2) - if maintype in allowed_mime_types, do: mime, else: "application/octet-stream" - end - defp set_content_type(conn, opts, filepath) do real_mime = MIME.from_path(filepath) - clean_mime = get_safe_mime_type(opts, real_mime) + clean_mime = Utils.get_safe_mime_type(opts, real_mime) put_resp_header(conn, "content-type", clean_mime) end diff --git a/lib/pleroma/web/plugs/utils.ex b/lib/pleroma/web/plugs/utils.ex new file mode 100644 index 000000000..770a3eeb2 --- /dev/null +++ b/lib/pleroma/web/plugs/utils.ex @@ -0,0 +1,14 @@ +# Akkoma: Magically expressive social media +# Copyright © 2024 Akkoma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Plugs.Utils do + @moduledoc """ + Some helper functions shared across several plugs + """ + + def get_safe_mime_type(%{allowed_mime_types: allowed_mime_types} = _opts, mime) do + [maintype | _] = String.split(mime, "/", parts: 2) + if maintype in allowed_mime_types, do: mime, else: "application/octet-stream" + end +end