josevalim

josevalim

Creator of Elixir

Static and session security fixes for Plug

Hello everyone,

Two vulnerabilities have been disclosed to Plug. Applications that provide file uploading functionality to a local filesystem are advised to upgrade immediately. Upgrade is also recommended for any other application that uses Plug, to ensure they follow the latest and best security practices.

We have released new Plug versions v1.0.4, v1.1.7, v1.2.3 and v1.3.2. If you can’t upgrade immediately, we also include fixes you can directly add to your applications.

Null Byte Injection in Plug.Static

Plug.Static is used for serving static assets, and is vulnerable to null byte injection. If file upload functionality is provided, this can allow users to bypass filetype restrictions.

We recommend all applications that provide file upload functionality and serve those uploaded files locally with Plug.Static to upgrade immediately or include the fix below. If uploaded files are rather stored and served from S3 or any other cloud storage, you are not affected.

  • Versions affected: Plug v1.3.1, v1.3.0, v1.2.2, v1.2.1, v1.2.0, v1.1.6, v1.1.5, v1.1.4, v1.1.3, v1.1.2, v1.1.1, v1.1.0, v1.0.3, v1.0.2, v1.0.1, v1.0.0
  • Versions fixed: Plug v1.3.2+, v1.2.3+, v1.1.7+, v1.0.4+
  • Author: Griffin Byatt <griffin.byatt[at]nccgroup[dot]trust>
  • Thanks to: Chip Durland, Raviv Cohen and Matthew Diaz

Temporary fix

Identify where plug Plug.Static is invoked in your application (in a Phoenix application this means the MyApp.Endpoint) and add the following lines before plug Plug.Static:

plug :safe_plug_static

defp safe_plug_static(conn, _) do
  Enum.any?(conn.path_info, &URI.decode(&1) =~ <<0>>) && raise "invalid path"
  conn
end

Arbitrary Code Execution in Cookie Serialization

The default serialization used by Plug session may result in code execution in certain situations. Keep in mind, however, the session cookie is signed and this attack can only be exploited if the attacker has access to your secret key as well as your signing/encryption salts. We recommend users to change their secret key base and salts if they suspect they have been leaked, regardless of this vulnerability.

  • Versions affected: Plug v1.3.1, v1.3.0, v1.2.2, v1.2.1, v1.2.0, v1.1.6, v1.1.5, v1.1.4, v1.1.3, v1.1.2, v1.1.1, v1.1.0, v1.0.3, v1.0.2, v1.0.1, v1.0.0
  • Versions fixed: Plug v1.3.2+, v1.2.3+, v1.1.7+, v1.0.4+
  • Author: Griffin Byatt <griffin.byatt[at]nccgroup[dot]trust>
  • Thanks to: Matthew Diaz

Temporary fix

If you can’t upgrade immediately, you can temporarily protect yourself by using a custom serializer Plug.Session serializer.

plug Plug.Session, serializer: MyApp.SafeSerializer

Where MyApp.SafeSerializer is defined as:

defmodule SafeSerializer do
  def encode(term) do
    {:ok, :erlang.term_to_binary(term)}
  end

  def decode(binary) do
    try do
      {:ok, safe_terms(:erlang.binary_to_term(binary))}
    rescue
      _ -> :error
    end
  end

  defp safe_terms(list) when is_list(list) do
    for item <- list, do: safe_terms(item)
    list
  end
  defp safe_terms(tuple) when is_tuple(tuple) do
    safe_tuple(tuple, tuple_size(tuple))
    tuple
  end
  defp safe_terms(map) when is_map(map) do
    for {key, value} <- map do
      safe_terms(key)
      safe_terms(value)
    end
    map
  end
  defp safe_terms(other) when is_atom(other) or is_number(other) or is_binary(other) or
                              is_pid(other) or is_reference(other) do
    other
  end
  defp safe_terms(other) do
    raise ArgumentError, "cannot deserialize #{inspect other}, the term is not safe for deserialization"
  end

  defp safe_tuple(tuple, 0), do: :ok
  defp safe_tuple(tuple, n), do
    safe_terms(:erlang.element(n, tuple))
    safe_tuple(tuple, n - 1)
  end
end

Final remarks

We want to thank the NCC Group for reporting those vulnerabilities.

NCC Group is a global expert in cyber security and risk mitigation, working with businesses to protect their brand, value and reputation against the ever-evolving threat landscape. Our Security Consulting services leverage our extensive knowledge of current security vulnerabilities, penetration testing techniques and software development best practices to enable organizations to secure their applications against ever-present threats. At NCC Group we can boast unrivaled talent and recognized world-class security expertise. Bringing together best in class security consultancies iSEC Partners, Intrepidus Group, Matasano, NCC Group and NGS we have created one of the largest, most respected security consultancies in the world.

Most Liked

dimitarvp

dimitarvp

Thanks for staying on top of things, much appreciated! I continue being impressed by you guys.

voltone

voltone

The access control issue @josevalim mentions is something I described in this post. I agree that most sites would probably implement sharing at the directory level, but some cloud syncing services have more fine-grained access control, for example for use in an enterprise environment.

Still, even if the example is a bit obscure, the important takeaway is this: until the underlying issue in the Erlang runtime is resolved, the path you’re inspecting and the path that’s actually being read from (or written to) may differ, so any application that build paths with user input should probably implement null-byte screening.

griffinbyatt

griffinbyatt

I wrote up a quick blog post on the vulnerabilities, which you can find here. It details the more “practical” method of achieving code execution in serialization functionality, as well as PoCs for anyone who wants to experiment with these locally.

bbense

bbense

I would encourage the Phoenix team to create a CVE for this vulnerablity if they have not already.

https://cve.mitre.org/about/faqs.html

josevalim

josevalim

Creator of Elixir

I have released Plug v1.3.3, v1.2.4, v1.1.8, v1.0.5 that also allows structs, bitstrings and improper lists to be deserialized.

Finally, when this thread is 7 days old, I will provide more information about the vulnerabilities. So if you haven’t upgraded yet, please do so.

Where Next?

Popular in News Top

Elixir
Release: https://github.com/elixir-lang/elixir/releases/tag/v1.11.2 1. Bug fixes Elixir [Code] Do not crash when getting docs for missi...
New
Elixir
Elixir v1.18 is an impressive release with improvements across the two main efforts happening within the Elixir ecosystem right now: set-...
New
josevalim
Hi everyone, We have just released v1.7.0-rc.0. The CHANGELOG and precompiled files are here: https://github.com/elixir-lang/elixir/rel...
New
josevalim
See the release notes: https://github.com/elixir-ecto/ecto/releases/tag/2.2.0-rc.0 To try it in your projects: {:ecto, "~&gt; 2.2.0-rc"...
New
Elixir
Release: Release v1.12.0-rc.1 · elixir-lang/elixir · GitHub 1. Enhancements Elixir [Code] Add Code.cursor_context/2 to return the conte...
New
Elixir
1. Enhancements Mix [mix compile.elixir] Do not run fixpoint computation on runtime dependencies. This should considerably improve compi...
New
Elixir
1. Enhancements Elixir [Code] Emit :defmodule tracing event on module definition Mix [Mix] Add Mix.install_project_dir/0 [Mix] Add env...
New
Elixir
1. Enhancements Elixir [Duration] Add Duration.to_iso8601/1 and Duration.from_iso8601/1 [Keyword] Add Keyword.intersect/2-3 to mirror th...
New
Elixir
Official announcement: Elixir v1.12 released - The Elixir programming language Elixir v1.12 is out with improvements to scripting, tight...
New
josevalim
Hi! :wave: I hope everyone is well! The Elixir team releases new versions every 6 months, typically every January and July. However, si...
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New

We're in Beta

About us Mission Statement