Compare commits

...

14 Commits

Author SHA1 Message Date
Haelwenn 1f4be2b349 Merge branch 'releases/2.5.4' into 'stable'
Release 2.5.4

See merge request pleroma/pleroma!3929
2023-08-05 08:12:25 +00:00
Haelwenn (lanodan) Monnier b631180b38 Release 2.5.4 2023-08-05 08:27:42 +02:00
Mark Felder cc848b78dc Document and test that XXE processing is disabled
https://vuln.be/post/xxe-in-erlang-and-elixir/
2023-08-05 08:23:04 +02:00
FloatingGhost 77d57c974a Add unit test for external entity loading 2023-08-05 08:23:04 +02:00
Mae fc10e07ffb Prevent XML parser from loading external entities 2023-08-05 08:23:04 +02:00
Haelwenn ff2f3862ab Merge branch 'release/2.5.3' into 'stable'
Release 2.5.3

See merge request pleroma/pleroma!3926
2023-08-04 09:45:48 +00:00
Haelwenn (lanodan) Monnier 57f7453748 Release 2.5.3 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 5ac2b7417d test: Fix warnings 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier c37561214a Force the use of amd64 runners for jobs using ci-base 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 76e408e42d release_runtime_provider_test: chmod config for hardened permissions
Git doesn't manages file permissions precisely enough for us.
2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 22df32b3f5 changelog: Entry for config permissions restrictions
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3135
2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier bd7381f2f4 instance gen: Reduce permissions of pleroma directories and config files 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 4befb3b1d0 Config: Restrict permissions of OTP config file 2023-08-04 09:49:53 +02:00
Mark Felder 18a0c923d0 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
2023-08-04 08:39:55 +02:00
17 changed files with 111 additions and 7 deletions

View File

@ -32,7 +32,13 @@ before_script:
after_script:
- rm -rf _build/*/lib/pleroma
.using-ci-base:
tags:
- amd64
build:
extends:
- .using-ci-base
stage: build
only:
changes: &build_changes_policy
@ -44,6 +50,8 @@ build:
- mix compile --force
spec-build:
extends:
- .using-ci-base
stage: test
only:
changes:
@ -57,6 +65,8 @@ spec-build:
- mix pleroma.openapi_spec spec.json
benchmark:
extends:
- .using-ci-base
stage: benchmark
when: manual
variables:
@ -71,6 +81,8 @@ benchmark:
- mix pleroma.load_testing
unit-testing:
extends:
- .using-ci-base
stage: test
only:
changes: *build_changes_policy
@ -94,6 +106,8 @@ unit-testing:
path: coverage.xml
unit-testing-erratic:
extends:
- .using-ci-base
stage: test
retry: 2
allow_failure: true
@ -129,6 +143,8 @@ unit-testing-erratic:
# - mix test --trace --only federated
unit-testing-rum:
extends:
- .using-ci-base
stage: test
only:
changes: *build_changes_policy
@ -162,6 +178,8 @@ lint:
- mix format --check-formatted
analysis:
extends:
- .using-ci-base
stage: test
only:
changes: *build_changes_policy

View File

@ -14,6 +14,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed
## 2.5.54
## Security
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem
## 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

View File

@ -0,0 +1 @@
Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem

View File

@ -0,0 +1 @@
Emoji pack loader sanitizes pack names

View File

@ -0,0 +1 @@
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories

View File

@ -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

View File

@ -20,6 +20,20 @@ def load(config, opts) do
with_runtime_config =
if File.exists?(config_path) do
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
%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

View File

@ -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),

View File

@ -29,7 +29,10 @@ def parse_document(text) do
{doc, _rest} =
text
|> :binary.bin_to_list()
|> :xmerl_scan.string(quiet: true)
|> :xmerl_scan.string(
quiet: true,
fetch_fun: fn _, _ -> raise "Resolving external entities not supported" end
)
{:ok, doc}
rescue

View File

@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
def project do
[
app: :pleroma,
version: version("2.5.2"),
version: version("2.5.4"),
elixir: "~> 1.11",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

View File

@ -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",

View File

@ -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

View File

@ -65,7 +65,7 @@ test "it works for incoming unqualified emoji reactions" do
object = Object.get_by_ap_id(data["object"])
assert object.data["reaction_count"] == 1
assert match?([[emoji, _]], object.data["reactions"])
assert match?([[^emoji, _]], object.data["reactions"])
end
test "it reject invalid emoji reactions" do

View File

@ -375,7 +375,7 @@ test "updates the user's background, upload_limit, returns a HTTP 413", %{
"pleroma_background_image" => new_background_oversized
})
assert user_response = json_response_and_validate_schema(res, 413)
assert _user_response = json_response_and_validate_schema(res, 413)
assert user.background == %{}
clear_config([:instance, :upload_limit], upload_limit)

View File

@ -180,5 +180,28 @@ test "respects xml content-type" do
{:ok, _data} = WebFinger.finger("pekorino@pawoo.net")
end
test "refuses to process XML remote entities" do
Tesla.Mock.mock(fn
%{
url: "https://pawoo.net/.well-known/webfinger?resource=acct:pekorino@pawoo.net"
} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/xml_external_entities.xml"),
headers: [{"content-type", "application/xrd+xml"}]
}}
%{url: "https://pawoo.net/.well-known/host-meta"} ->
{:ok,
%Tesla.Env{
status: 200,
body: File.read!("test/fixtures/tesla_mock/pawoo.net_host_meta")
}}
end)
assert :error = WebFinger.finger("pekorino@pawoo.net")
end
end
end

View File

@ -0,0 +1,10 @@
defmodule Pleroma.Web.XMLTest do
use Pleroma.DataCase, async: true
alias Pleroma.Web.XML
test "refuses to load external entities from XML" do
data = File.read!("test/fixtures/xml_external_entities.xml")
assert(:error == XML.parse_document(data))
end
end