From 2c795094535537a8607cc0d3b7f076a609636f40 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Thu, 3 Aug 2023 13:08:37 -0400 Subject: [PATCH 1/6] Resolve information disclosure vulnerability through emoji pack archive download endpoint The pack name has been sanitized so an attacker cannot upload a media file called pack.json with their own handcrafted list of emoji files as arbitrary files on the filesystem and then call the emoji pack archive download endpoint with a pack name crafted to the location of the media file they uploaded which tricks Pleroma into generating a zip file of the target files the attacker wants to download. The attack only works if the Pleroma instance does not have the AnonymizeFilename upload filter enabled, which is currently the default. Reported by: graf@poast.org --- changelog.d/emoji-pack-sanitization.security | 1 + lib/pleroma/emoji/pack.ex | 1 + test/pleroma/emoji/pack_test.exs | 4 ++++ 3 files changed, 6 insertions(+) create mode 100644 changelog.d/emoji-pack-sanitization.security diff --git a/changelog.d/emoji-pack-sanitization.security b/changelog.d/emoji-pack-sanitization.security new file mode 100644 index 000000000..f3218abd4 --- /dev/null +++ b/changelog.d/emoji-pack-sanitization.security @@ -0,0 +1 @@ +Emoji pack loader sanitizes pack names diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index a361ea200..6e58f8898 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -285,6 +285,7 @@ def update_metadata(name, data) do @spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()} def load_pack(name) do + name = Path.basename(name) pack_file = Path.join([emoji_path(), name, "pack.json"]) with {:ok, _} <- File.stat(pack_file), diff --git a/test/pleroma/emoji/pack_test.exs b/test/pleroma/emoji/pack_test.exs index 18b99da75..00001abfc 100644 --- a/test/pleroma/emoji/pack_test.exs +++ b/test/pleroma/emoji/pack_test.exs @@ -90,4 +90,8 @@ test "add emoji file", %{pack: pack} do assert updated_pack.files_count == 1 end + + test "load_pack/1 ignores path traversal in a forged pack name", %{pack: pack} do + assert {:ok, ^pack} = Pack.load_pack("../../../../../dump_pack") + end end From 8cc8100120abdbf26cfe4cdac2c0a012d7919e05 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 22 Jun 2023 00:46:52 +0200 Subject: [PATCH 2/6] Config: Restrict permissions of OTP config file --- lib/pleroma/config/release_runtime_provider.ex | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/pleroma/config/release_runtime_provider.ex b/lib/pleroma/config/release_runtime_provider.ex index 91e5f1a54..9ec0f975e 100644 --- a/lib/pleroma/config/release_runtime_provider.ex +++ b/lib/pleroma/config/release_runtime_provider.ex @@ -20,6 +20,20 @@ def load(config, opts) do with_runtime_config = if File.exists?(config_path) do + # + %File.Stat{mode: mode} = File.lstat!(config_path) + + if Bitwise.band(mode, 0o007) > 0 do + raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}" + end + + if Bitwise.band(mode, 0o020) > 0 do + raise "Configuration at #{config_path} has group-wise write permissions, execute the following: chmod g-w #{config_path}" + end + + # Note: Elixir doesn't provides a getuid(2) + # so cannot forbid group-read only when config is owned by us + runtime_config = Config.Reader.read!(config_path) with_defaults From 69caedc591bd61029f897f37ef7ecddd470cf935 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 22 Jun 2023 00:58:05 +0200 Subject: [PATCH 3/6] instance gen: Reduce permissions of pleroma directories and config files --- lib/mix/tasks/pleroma/instance.ex | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 5c93f19ff..5d8b254a2 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -266,12 +266,20 @@ def run(["gen" | rest]) do config_dir = Path.dirname(config_path) psql_dir = Path.dirname(psql_path) + # Note: Distros requiring group read (0o750) on those directories should + # pre-create the directories. [config_dir, psql_dir, static_dir, uploads_dir] |> Enum.reject(&File.exists?/1) - |> Enum.map(&File.mkdir_p!/1) + |> Enum.each(fn dir -> + File.mkdir_p!(dir) + File.chmod!(dir, 0o700) + end) shell_info("Writing config to #{config_path}.") + # Sadly no fchmod(2) equivalent in Elixir… + File.touch!(config_path) + File.chmod!(config_path, 0o640) File.write(config_path, result_config) shell_info("Writing the postgres script to #{psql_path}.") File.write(psql_path, result_psql) @@ -290,8 +298,7 @@ def run(["gen" | rest]) do else shell_error( "The task would have overwritten the following files:\n" <> - (Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <> - "Rerun with `--force` to overwrite them." + Enum.map_join(will_overwrite, &"- #{&1}\n") <> "Rerun with `--force` to overwrite them." ) end end From 9f0ad901ed4f8f0ad3e1d896fd41d25b93a97d76 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Thu, 22 Jun 2023 01:00:25 +0200 Subject: [PATCH 4/6] changelog: Entry for config permissions restrictions Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3135 --- changelog.d/otp_perms.security | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/otp_perms.security diff --git a/changelog.d/otp_perms.security b/changelog.d/otp_perms.security new file mode 100644 index 000000000..a3da1c677 --- /dev/null +++ b/changelog.d/otp_perms.security @@ -0,0 +1 @@ +- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories \ No newline at end of file From 65ef8f19c5e21baadfa7daabdbd37fb9a1fbf863 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 4 Aug 2023 07:16:50 +0200 Subject: [PATCH 5/6] release_runtime_provider_test: chmod config for hardened permissions Git doesn't manages file permissions precisely enough for us. --- test/pleroma/config/release_runtime_provider_test.exs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/pleroma/config/release_runtime_provider_test.exs b/test/pleroma/config/release_runtime_provider_test.exs index e6d10b13e..8d2a93d6c 100644 --- a/test/pleroma/config/release_runtime_provider_test.exs +++ b/test/pleroma/config/release_runtime_provider_test.exs @@ -17,6 +17,8 @@ test "loads release defaults config and warns about non-existent runtime config" end test "merged runtime config" do + assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640) + merged = ReleaseRuntimeProvider.load([], config_path: "test/fixtures/config/temp.secret.exs") @@ -25,6 +27,8 @@ test "merged runtime config" do end test "merged exported config" do + assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640) + ExUnit.CaptureIO.capture_io(fn -> merged = ReleaseRuntimeProvider.load([], @@ -37,6 +41,9 @@ test "merged exported config" do end test "runtime config is merged with exported config" do + assert :ok == File.chmod!("test/fixtures/config/temp.secret.exs", 0o640) + assert :ok == File.chmod!("test/fixtures/config/temp.exported_from_db.secret.exs", 0o640) + merged = ReleaseRuntimeProvider.load([], config_path: "test/fixtures/config/temp.secret.exs", From 6a0fd77c48946b4b2100585b4f32d125680f5f82 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 4 Aug 2023 05:13:28 +0200 Subject: [PATCH 6/6] Release 2.5.53 --- CHANGELOG.md | 6 ++++++ mix.exs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a1bbb8f..87e9c5298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact) +## 2.5.3 + +### Security +- Emoji pack loader sanitizes pack names +- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories + ## 2.5.2 ### Security diff --git a/mix.exs b/mix.exs index fc4e87ee3..115e7113f 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do def project do [ app: :pleroma, - version: version("2.5.52"), + version: version("2.5.53"), elixir: "~> 1.11", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix] ++ Mix.compilers(),