Skip to content

Commit

Permalink
Guard against timing attacks using secure_compare (#32)
Browse files Browse the repository at this point in the history
* Guard against timing attacks using secure_compare

As pointed out by Sergey Popal, the straightforward binary comparison was
vulnerable to timing attacks.

See https://codahale.com/a-lesson-in-timing-attacks/
https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html

* Bump version and update README.
  • Loading branch information
paulanthonywilson committed Dec 12, 2017
1 parent d192f1c commit 343efe6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
28 changes: 18 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@ The plug can be configured to use:

2) Your own custom authentication function

Note that if using option (1), prior to 2.2.1 the library was vulnerable to [timing attacks](https://codahale.com/a-lesson-in-timing-attacks/);
we suggest updating `~> 2.2.2`.

If you are using your own custom authentication function, then you are are on your own.
([Plug.Crypto.secure_compare/2](https://hexdocs.pm/plug/1.5.0-rc.0/Plug.Crypto.html#secure_compare/2) is something that may help you compare
binaries in constant time.)


## How to use

Add the package as a dependency in your Elixir project using something along the lines of:
```elixir
defp deps do
[{:basic_auth, "~> 2.2"}]
[{:basic_auth, "~> 2.2.2"}]
end
```

Expand All @@ -38,8 +46,8 @@ plug BasicAuth, use_config: {:your_app, :your_config}
]
```

As of v2.2.0, all configuration is read at runtime to support using
[REPLACE_OS_VARS](http://michal.muskala.eu/2017/07/30/configuring-elixir-libraries.html#distillerys-replaceosvars)
All configuration is read at runtime to support using
[REPLACE_OS_VARS](http://michal.muskala.eu/2017/07/30/configuring-elixir-libraries.html#distillerys-replaceosvars)
as part of a release.

or choose to get one (or all) from environment variables, eg
Expand Down Expand Up @@ -80,20 +88,20 @@ It will receive a connection, username, and password.

Easy as that!


### Authenticating only for specific actions

If you're looking to authenticate only for a subset of actions in a controller you can use plug's `when action in` syntax as shown below

```elixir
plug BasicAuth, [use_config: {:your_app, :your_config}] when action in [:edit, :delete]
```
```elixir
plug BasicAuth, [use_config: {: your_app, : your_config}] when action in [:edit, :delete]
```

additionally you can exclude specific actions using `not`

```elixir
plug BasicAuth, [use_config: {:your_app, :your_config}] when not action in [:index, :show]
```

```elixir
plug BasicAuth, [use_config: {: your_app, : your_config}] when not action in [:index, :show]
```
## Testing controllers with Basic Auth

If you're storing credentials within configuration files, we can reuse them within our test files
Expand Down
4 changes: 3 additions & 1 deletion lib/basic_auth/configured.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ defmodule BasicAuth.Configured do

defstruct config_options: nil

alias Plug.Crypto

def init(config_options) do
%__MODULE__{config_options: config_options}
end
Expand All @@ -23,7 +25,7 @@ defmodule BasicAuth.Configured do
end

defp check_token(conn, token, options = %__MODULE__{config_options: config_options}) do
if token == configured_token(config_options) do
if Crypto.secure_compare(token, configured_token(config_options)) do
conn
else
send_unauthorised_response(conn, options)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule BasicAuth.Mixfile do
[app: :basic_auth,
description: "Basic Authentication Plug",
package: package(),
version: "2.2.1",
version: "2.2.2",
elixir: "~> 1.0",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
Expand Down

0 comments on commit 343efe6

Please sign in to comment.