Security Scanning Your Phoenix App
Sobelow is a security-focused static analysis tool for the Phoenix framework. It is produced by NCC Group, a cyber-security firm whose roots go back to June 1999.
At the time of this writing, the current version is 0.3.6 and it has been gaining traction in the Elixir/Phoenix communities.
Why Run Security Scans?
First, it should be a matter of personal responsibility to your product and your users that you try to protect your application and your user’s data.
Second, various certifications like PCI Compliance can require things like automated static-analysis security scans or security code reviews of all changes to the system.
Third, what coding habits do you have that might be a security risk? Sobelow can be that third-party reviewer to challenge your long-held assumptions.
I work at a fast-paced FinTech startup with agile workflows. The best option is to have security scans automatically performed on PRs before they are merged. Some benefits to having them automated is you don’t forget to run the checks and it helps identify new code changes that could have security problems.
Install Options
The project recommends installing it outside of the project to be scanned like this.
This works well when you want to scan other people’s projects without modifying their dependencies.
It also works to add it to your project’s mix.exs
if that makes more sense for
your situation.
Running a Scan
Running your first scan is easy.
There are a number of command-line options and new options were recently added so it is worth checking for current documentation.
We Need Code to Scan!
I did a quick Github search for OpenSource Phoenix applications that I could use for this post and found one under active development. This will work perfectly!
Setup steps before we can test sobelow
on the project.
- Clone the project locally
- Make it able to compile
- Nothing more needed! It’s “static-analysis” remember?
Run sobelow
on the project…
Note: Unfortunately, the color coding doesn’t translate to my copy of the text here. So just note that it is sorted with “High Confidence” items higher up then descending to “Medium” and “Low”. The colors change accordingly.
Interesting output! Now what does it mean? It is worth noting what the Sobelow project says about “False Positives”:
Sobelow favors over-reporting versus under-reporting. As such, you may find a number of false positives in a typical scan. These findings may be individually ignored by adding a @sobelow_skip mark, along with a list of modules, before the function definition.
So we need to check them personally and determine if it is a problem or not.
Let’s try out the command-line option --with-code
and see if that helps
give context to the warnings. I won’t include the full output for brevity’s sake.
I double-checked the router file and yes, it is missing the plug
:protect_from_forgery
call you would otherwise expect.
Well that’s nice! A recent sobelow
feature is checking for known
vulnerabilities in the project’s dependencies. And yes, the project’s mix.exs
file is pinned to an older phoenix version. Time to upgrade!
Here’s another one with a good code sample.
Again, the coloring doesn’t come across here. But the code being pointed out is this…
After checking the router, it is clear that this is indeed taking user submitted
data and interpolating that text into a command-line path. This means submitting
a “temp_file” value like “../somewhere/else
” poses a risk of accessing data
from anywhere on disk. I verified in the router that in order to even make this
call, you must be an authenticated user. This prompts the question, “How much do
you trust all of your users?”
I notified the project on Github of the issues and they have already addressed them.
It is also interesting how sobelow
displays the function as
def(view_uploaded_data(...))
. Looking at the actual file, it was as
you’d expect with def view_uploaded_data(...)
. I guess that’s exposing the
reality that def
is an Elixir macro. :)
Now you’ve seen some real-world examples of how sobelow
can help your project.
Umbrella Projects
Sobelow is only designed for scanning Phoenix applications. So it doesn’t scan a
standard mix new
project. I follow the pattern where my projects are umbrella
applications with the Phoenix project being generated without Ecto. This really
reduces the utility of sobelow.
Running it from the root of my project it returns this…
Luckily, the --root
option lets me specify the path to the Phoenix app in my
project.
It’s totally true. My personal project that lives only on my machine hasn’t been setup for HTTPS yet. But, it’s a nice reminder that this should be a priority before I deploy outside of my home.
But it found nothing else. Since all my Ecto queries are done in other apps where the business logic lives, how comfortable should I be that this didn’t find anything? I’m not sure. Sobelow has been advancing quickly recently. I’m hopeful that it will grow in sophistication over time.
Work Project Scan Results
I started using Sobelow on our backend system at work. Now, I got the same “HTTPS Not Enabled”. However, in this case it isn’t a problem. Our production deployment has the web application behind load-balancers that are terminating the HTTPS connection. So our app doesn’t have that responsibility. How do we tell Sobelow this is okay?
Disable a Check
To disable the “HTTPS Not Enabled” check, I searched the sobelow project code for some error text and found it easily enough.
This one is not a specific line of code to disable, it is turning off the check.
The -i
is to “ignore” that check.
Valid Finds
Sobelow found a valid “Unsafe String.to_atom
- High Confidence” issue. At
work, many of the backend developers are new to Elixir. You can’t expect
everyone to be familiar with the details of a new language and its runtime. A
member of our team took client provided raw param data and performed
String.to_atom
on it. Atoms in Elixir are like Symbols in Ruby. Elixir atoms
are not garbage collected. This allows a malicious user to arbitrarily create
them through an HTTP POST which can be abused to consume system resources until
the server crashes. Resulting in a “denial of service” attack.
This find lets us have an “education moment”. So it works!
Automated Scanning
The option --exit
returns a non-zero return code when problems are found. This
makes it easy for an automated system to “fail” the process when a new
vulnerability is introduced.
From the docs:
The exit option accepts a confidence threshold (low, medium, or high), and will return a non-zero exit status at or above that threshold.
So our project at work can run the tests on the multiple phoenix applications in the umbrella and automatically fail the code checks when new problems are introduced.
Conclusion
Sobelow is the first static-analysis security scanner for Phoenix that I’m aware of. I looked around a lot. At work, we have PCI Compliance requirements in addition to our desire to have a completely secure system. Sobelow came along at the perfect time for us. It has become part of our automated processes for testing code quality.
Give it a try on your Phoenix projects and share your results!