Check out the Alchemist's Edition

#54: Detect Security Issues with Sobelow

Elixir 1.6

Phoenix 1.3

Sobelow 0.7.0

View source on GitHub


Sign up for our newsletter to get notified when new episodes drop

In this episode we’re going to be taking a look at how we can secure Phoenix applications. Specifically we’ll look at how we can use Sobelow to discover identify potential vulnerabilities. First off - what is Sobelow?

Sobelow is a security focused static analysis tool designed specifically for the Phoenix framework. It can detect certain security issues like Cross-Site Scripting, SQL injection, and Insecure Configuration among others. It’s maintained by Griffin Byatt at NCC Group. He gave a really great talk about it at ElixirConf 2017, which I’ve linked to here.

Alright so now that we know what it is, let’s see how we can use Sobelow to check our application for vulnerabilities. First off we’ll install Sobelow. And with it installed let’s run it from the root of our Phoenix application.

$ mix archive.install hex sobelow
$ mix sobelow
##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

Missing Content-Security-Policy - High Confidence
Pipeline: browser:4

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 11
Type: secret_key_base

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 15
Type: password

-----------------------------------------------

HTTPS Not Enabled - High Confidence

-----------------------------------------------

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query

-----------------------------------------------

... SCAN COMPLETE ...

Great that’s all it took to download Sobelow and scan our application for vulnerabilities. Now in a production application we’d want to go through and address these concerns, but for the purposes of this episode, let’s see how we can customize Sobelow to fit our application.

Now let’s look at the results that Sobelow returned. For each issue detected we’re shown a warning that tells us how confident it is about the potential vulnerability. For our app we have 4 “High Confidence” warnings and 1 “Low Confidence”.

If we wanted to display the offending line of each module in the results, we can run Sobelow with the “verbose” option.

$ mix sobelow -v
##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

Missing Content-Security-Policy - High Confidence
Pipeline: browser:4


pipeline(:browser) do
  plug(:accepts, ["html"])
  plug(:fetch_session)
  plug(:fetch_flash)
  plug(:protect_from_forgery)
  plug(:put_secure_browser_headers)
end

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 11
Type: secret_key_base


config(:teacher, TeacherWeb.Endpoint, secret_key_base: "...2wr6epHOFGtbLkgdpbqYC2vMSa8R/wpmniIT1ykktRC6")

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 15
Type: password


config(:teacher, Teacher.Repo, adapter: Ecto.Adapters.Postgres, username: "postgres", password: "postgres", database: "teacher_prod", pool_size: 15)

-----------------------------------------------

HTTPS Not Enabled - High Confidence

HTTPS configuration details could not be found in `prod.exs`.

-----------------------------------------------

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query


def(bad_func(query)) do
  Repo.query(query)
end

-----------------------------------------------

... SCAN COMPLETE ...

Now we can see what’s on the the exact lines Sobelow is warning us about. In fact, we can see all the supported options by running $ mix help sobelow.

And all our command line options are printed. But if we scroll down we also see a list of “Supported Modules”. Different categories are broken up into these modules. If we want more information about a warning, we can use these modules with the “details” option to get them.

$ mix help sobelow
Sobelow is a static analysis tool for discovering vulnerabilities in Phoenix
applications.

This tool should be run in the root of the project directory with the following
command:

    mix sobelow

## Command line options

  • --root -r - Specify application root directory
  • --verbose -v - Print vulnerable code snippets
  • --ignore -i - Ignore modules
  • --ignore-files - Ignore files
  • --details -d - Get module details
  • --all-details - Get all module details
  • --private - Skip update checks
  • --skip - Skip functions flagged with @sobelow_skip
  • --router - Specify router location
  • --exit - Return non-zero exit status
  • --format - Specify findings output format
  • --quiet - Return no output if there are no findings
  • --compact - Minimal, single-line findings
...

In fact, if we go back to our warnings. Let’s get some more information about our first one. We’ll use the “details” option giving it the name of the module we want more inforamtion about, in this case Config.CSP.

$ mix sobelow -d Config.CSP
# Missing Content-Security-Policy

Content-Security-Policy is an HTTP header that helps mitigate a number of
attacks, including Cross-Site Scripting.

Read more about CSP here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP

Missing Content-Security-Policy is flagged by sobelow when a pipeline
implements the :put_secure_browser_headers plug, but does not provide a
Content-Security-Policy header in the custom headers map.

Documentation on the put_secure_browser_headers plug function can be found
here:
https://hexdocs.pm/phoenix/Phoenix.Controller.html#put_secure_browser_headers/2

Content-Security-Policy checks can be ignored with the following command:

    $ mix sobelow -i Config.CSP

And we see some information is printed about the “Content-Security-Policy header”. Now if we want to ignore warnings for this we can run Sobelow with the “ignore” option.

Let’s test it out. We’ll run $ mix sobelow -i Config.CSP.

$ mix sobelow -i Config.CSP
Checking Sobelow version...

##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 11
Type: secret_key_base

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 15
Type: password

-----------------------------------------------

HTTPS Not Enabled - High Confidence

-----------------------------------------------

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query

-----------------------------------------------

... SCAN COMPLETE ...

And we can see our “Missing Content-Security-Policy” warning isn’t printed.

We can ignore multiple modules too. Let’s also ignore our “HTTPS Not Enabled” warning. We’ll run our command again separating the modules we want to ignore with a comma:

$ mix sobelow -i Config.CSP,Config.HTTPS
##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 11
Type: secret_key_base

-----------------------------------------------

Hardcoded Secret - High Confidence
File: config/prod.secret.exs - line 15
Type: password

-----------------------------------------------

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query

-----------------------------------------------

... SCAN COMPLETE ...

Now two of our warnings are coming from the same file - our prod.secret.exs.

Sobelow is telling us that our secret_key_base and password are hardcoded in our prod.secret.exs. Now if we wanted to ignore all the warnings from a specific file, Sobelow gives us a way to do that too. We can use the “ignore-files” option with the file we want to ignore.

$ mix sobelow -i Config.CSP,Config.HTTPS --ignore-files config/prod.secret.exs
##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query

-----------------------------------------------

... SCAN COMPLETE ...

Now if this became the standard set of options for this app, remembering to run all of them would get a little tedious. Luckily Sobelow makes is easy to create a configuration file that will run these options for us. We can append the “—save-config” flag. This will create a .sobelow-conf at the root of our project. Great it looks like our config was created. Let’s clear the screen and then read it. We see the modules we specified are ignored, along with the prod.secret.exs And now to run Sobelow with our config, we can use the “—config” flag.

$ mix sobelow -i Config.CSP,Config.HTTPS --ignore-files config/prod.secret.exs --save-config
Updated .sobelow-conf
$ cat .sobelow-conf
[
  verbose: false,
  private: false,
  skip: false,
  router: "",
  exit: "false",
  format: "txt",
  ignore: ["Config.CSP", "Config.HTTPS"],
  ignore_files: ["/path/to/teacher/config/prod.secret.exs"]
]
$ mix sobelow --config
##############################################
#                                            #
#          Running Sobelow - v0.7.0          #
#  Created by Griffin Byatt - @griffinbyatt  #
#     NCC Group - https://nccgroup.trust     #
#                                            #
##############################################

SQL injection - Low Confidence
File: lib/teacher/records/records.ex - bad_func:11
Variable: query

-----------------------------------------------

... SCAN COMPLETE ...

And perfect, it’s using our specified configuration and we see only one warning printed. Now let’s look at our last offending function. We’ll open our records.ex module. And we’ll go to the bad_func function. Here our function is taking a query and executing it, which could contain potentially unsafe input. While in practice we’d probably re-write this, we’ll use it to demonstrate how we can skip individual functions that raise warnings. Above our function we’ll add a comment “sobelow_skip” along with a list of the modules we want to skip.

lib/teacher/records/records.ex

...
# sobelow_skip ["SQL.Query"]
def bad_func(query) do
  Repo.query(query) # please don't do this
end
...

Now we need to run Sobelow with the “—skip” flag. Because we created a config for Sobelow, let’s open it.

And we’ll update our “skip” to “true”.

.sobelow-conf

[
  ...
  skip: false,
  ...

]

Great, now let’s go ahead and run Sobelow one last time. And it skipped the function we specified.

Sobelow is a great project that helps make you aware of the potential security vulnerabilities in your project. I hope this gives a introduction on how you can use it and shows how easy it is identify the parts of your application that may have vulnerabilities.