|
1 |
| -# SafeURL |
2 |
| -SafeURL is a library that aids developers in protecting against a class of vulnerabilities known as Server Side Request Forgery. It does this by validating a URL against a configurable white or black list before making an HTTP request. SafeURL is open-source and licensed under MIT. |
| 1 | +SafeURL |
| 2 | +======= |
| 3 | + |
| 4 | +<!--[![Build Status][badge-github]][github-build]--> |
| 5 | +[![Version][badge-version]][hexpm] |
| 6 | +[![Downloads][badge-downloads]][hexpm] |
| 7 | +[![License][badge-license]][github-license] |
| 8 | + |
| 9 | + |
| 10 | +> SSRF Protection in Elixir 🛡️ |
| 11 | +
|
| 12 | + |
| 13 | +SafeURL is a library that aids developers in protecting against a class of vulnerabilities |
| 14 | +known as Server Side Request Forgery. It does this by validating a URL against a configurable |
| 15 | +allow or block list before making an HTTP request. SafeURL is open-source and licensed under |
| 16 | +MIT. |
| 17 | + |
| 18 | +This library was originally created by Nick Fox at [Include Security][includesecurity], |
| 19 | +with substantial improvements contributed by the [Slab][slab] team. As of January 2022, this |
| 20 | +library is now officially maintained by Slab. |
| 21 | + |
| 22 | +See the [Documentation][docs] on HexDocs. |
| 23 | + |
| 24 | +<br> |
| 25 | + |
| 26 | + |
3 | 27 |
|
4 |
| -This library was originally created by Nick Fox at [Include Security](https://github.com/IncludeSecurity), with substantial improvements contributed by the [Slab](https://github.com/slab) team. As of January 2022, this library is now maintained by Slab. |
5 | 28 |
|
6 | 29 | ## Installation
|
7 |
| -This package is not yet available in hex, so it must be installed from GitHub by adding the following to |
8 |
| -`mix.exs`: |
| 30 | + |
| 31 | +Add `safeurl` to your project dependencies in `mix.exs`: |
9 | 32 |
|
10 | 33 | ```elixir
|
11 | 34 | def deps do
|
12 |
| - [ |
13 |
| - {:safeurl, github: "includesecurity/elixir-safeurl"} |
14 |
| - ] |
| 35 | + [{:safeurl, "~> 0.1.0"}] |
15 | 36 | end
|
16 | 37 | ```
|
17 | 38 |
|
| 39 | +<br> |
| 40 | + |
| 41 | + |
| 42 | + |
| 43 | + |
18 | 44 | ## Usage
|
19 |
| -SafeURL wraps around [HTTPoison](https://github.com/edgurgel/httpoison) and |
20 |
| -works by resolving the IP address from a supplied URL and validating it |
21 |
| -against a blacklist or whitelist before sending the request. By default, all |
22 |
| -internal/reserved CIDR ranges are blacklisted, and developers can add |
23 |
| -additional CIDR ranges to these lists with the `:blacklist` parameter, or |
24 |
| -instead use a whitelist approach with `:whitelist`. |
| 45 | + |
| 46 | +`SafeURL` blocks private/reserved IP addresses are by default, and users can add additional |
| 47 | +CIDR ranges to the blocklist, or alternatively allow specific CIDR ranges to which the |
| 48 | +application is allowed to make requests. |
| 49 | + |
| 50 | +You can use `allowed?/2` or `validate/2` to check if a URL is safe to call, or just call |
| 51 | +it directly via `get/4` which will validate it automatically before calling, and return an |
| 52 | +error if it is not. |
| 53 | + |
| 54 | + |
| 55 | +### Examples |
25 | 56 |
|
26 | 57 | ```elixir
|
27 |
| -# Only block private IP ranges |
28 |
| -iex> SafeURL.get("https://includesecurity.com") |
29 |
| -{:ok, %HTTPoison.Response{...}} |
| 58 | +iex> SafeURL.allowed?("https://includesecurity.com") |
| 59 | +true |
30 | 60 |
|
31 |
| -# Blacklist 8.8.0.0/16 in addition to all private ranges |
32 |
| -iex> SafeURL.get("https://includsecurity.com", blacklist: ["8.8.0.0/16"]) |
33 |
| -{:ok, %HTTPoison.Response{...}} |
| 61 | +iex> SafeURL.validate("http://google.com/", schemes: ~w[https]) |
| 62 | +{:error, :restricted} |
34 | 63 |
|
35 |
| -# Only allow requests to hosts on 10.0.0.0/24 |
36 |
| -iex> SafeURL.get("https://includesecurity.com", whitelist: ["10.0.0.0/24"]) |
| 64 | +iex> SafeURL.validate("http://230.10.10.10/") |
37 | 65 | {:error, :restricted}
|
38 | 66 |
|
39 |
| -# Pass some headers and options to HTTPoison |
40 |
| -iex> SafeURL.get("https://includesecurity.com", [], [{"User-Agent", "elixir/1.11.3"}], follow_redirect: false) |
| 67 | +iex> SafeURL.validate("http://230.10.10.10/", block_reserved: false) |
| 68 | +:ok |
| 69 | + |
| 70 | +iex> SafeURL.get("https://10.0.0.1/ssrf.txt") |
| 71 | +{:error, :restricted} |
| 72 | + |
| 73 | +iex> SafeURL.get("https://google.com/") |
| 74 | +{:ok, %HTTPoison.Response{...}} |
41 | 75 | ```
|
42 | 76 |
|
43 |
| -If you only need to validate a URL and want to make the request yourself, you |
44 |
| -can use `SafeURL.validate_url()` instead: |
| 77 | + |
| 78 | +### Configuration |
| 79 | + |
| 80 | +`SafeURL` can be configured to customize and override validation behaviour by passing the |
| 81 | +following options: |
| 82 | + |
| 83 | + * `:block_reserved` - Block reserved/private IP ranges. Defaults to `true`. |
| 84 | + |
| 85 | + * `:blocklist` - List of CIDR ranges to block. This is additive with `:block_reserved`. |
| 86 | + Defaults to `[]`. |
| 87 | + |
| 88 | + * `:allowlist` - List of CIDR ranges to allow. If specified, blocklist will be ignored. |
| 89 | + Defaults to `[]`. |
| 90 | + |
| 91 | + * `:schemes` - List of allowed URL schemes. Defaults to `["http, "https"]`. |
| 92 | + |
| 93 | + |
| 94 | +These options can be passed to the function directly or set globally in your `config.exs` |
| 95 | +file: |
45 | 96 |
|
46 | 97 | ```elixir
|
47 |
| -iex> SafeURL.validate_url("https://acme.corp.internal") |
48 |
| -{:error, :restricted} |
| 98 | +config :safeurl, |
| 99 | + block_reserved: true, |
| 100 | + blocklist: ~w[100.0.0.0/16], |
| 101 | + schemes: ~w[https] |
49 | 102 | ```
|
| 103 | + |
| 104 | +Find detailed documentation on [HexDocs][docs]. |
| 105 | + |
| 106 | +<!-- |
| 107 | + TODO: Add section explaining how to use SafeURL with various HTTP libraries |
| 108 | + such as HTTPoison, Tesla, etc. once we remove HTTPoison as a dependency. |
| 109 | +--> |
| 110 | + |
| 111 | +<br> |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | +## Contributing |
| 117 | + |
| 118 | + - [Fork][github-fork], Enhance, Send PR |
| 119 | + - Lock issues with any bugs or feature requests |
| 120 | + - Implement something from Roadmap |
| 121 | + - Spread the word :heart: |
| 122 | + |
| 123 | +<br> |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | +## License |
| 129 | + |
| 130 | +This package is available as open source under the terms of the [MIT License][github-license]. |
| 131 | + |
| 132 | +<br> |
| 133 | + |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +<!--[badge-github]: https://github.com/slab/delta-elixir/actions/workflows/ci.yml/badge.svg--> |
| 138 | +[badge-version]: https://img.shields.io/hexpm/v/safeurl.svg |
| 139 | +[badge-license]: https://img.shields.io/hexpm/l/safeurl.svg |
| 140 | +[badge-downloads]: https://img.shields.io/hexpm/dt/safeurl.svg |
| 141 | + |
| 142 | +[hexpm]: https://hex.pm/packages/safeurl |
| 143 | +[github-license]: https://github.com/slab/safeurl-elixir/blob/master/LICENSE |
| 144 | +[github-fork]: https://github.com/slab/safeurl-elixir/fork |
| 145 | + |
| 146 | +[docs]: https://hexdocs.pm/safeurl |
| 147 | +[slab]: https://slab.com/ |
| 148 | +[includesecurity]: https://github.com/IncludeSecurity |
| 149 | + |
| 150 | + |
0 commit comments