LostKobrakai
32) ElixirConf 2017: Plugging the Security Holes in Your Phoenix Application
After having watched the talk I’m wondering if this would also be a good opportunity to gather examples / tips about how to prevent or mitigate the mentioned issues. I’d expect the e.g. for the mentioned session issue there might already be examples out there. Also I’m especially curious about the last topic on mass assignment. How do you guys handle changesets which are allowed to change things like admin flags or alike, so at best they’re not accidentally usable from any frontend forms.
Most Liked
LostKobrakai
I’ll start by adding my captain obvious solution to prevent accidental changes to admin flag fields: Don’t handle it through the params sent to changeset/2, but only allow them to be changed by custom functions.
def make_admin(%User{} = user) do
user
|> Ecto.Changeset.change(%{is_admin: true})
|> Repo.update()
end
def put_admin_flag(%Ecto.Changeset{} = changeset) do
Ecto.Changeset.change(changeset, %{is_admin: true})
end
This way in each places, where setting that flag should indeed be possible it has to be done explicitly, independent to any changeset/2 functions/params.
benwilson512
One person’s duplication is another’s de-coupling. ![]()
griffinbyatt
I’ll comment with some of my thoughts a bit later when I have some more time. Until then, I wanted to say thanks for posting, and I’m happy to answer questions about the content if anyone has any!
griffinbyatt
The nice thing about most of the vulnerabilities I talked about is that Phoenix does a good job of pushing you in the right direction, so there often aren’t too many ways to make mistakes. This means that 1) Once you are aware of the issues, they become much easier to avoid, and 2) A lot of these issues are easy to detect in an automated fashion, so a tool like Sobelow can simply/reliably help you avoid them.
That leaves “logical” issues like session/auth handling and “mass assignment” type vulns. These tend to be less Phoenix-specific, and are common across applications. Mass Assignment vulnerabilities are a pretty classic Rails issue, and have been fairly highly publicized, but the Rails community still has issues with it. It’s a pretty hard thing to mitigate.
I think part of the problem people have w/ the changeset functionality is that, because the changeset function is generated for you (and because it’s called “changeset”), the changeset function feels very “official” and safe.
^^ This is definitely a solid way to start dealing with sensitive fields! Another is to have a bunch of unique, very explicit changesets. E.g. registration_changeset, admin_changeset.
Also, when possible, explicitly passing params is a good move. For example, something like:
User.registration_changeset(%{email: email, username: username})
People tend to like this recommendation less b/c it can cause a lot of duplication. But I like it, because even if something unfortunate changes w/in the changeset function, you’re still safe ![]()
michalmuskala
You would define multiple changeset functions in that case. In general, in ecto, almost no configuration or validation is “global”. There is nothing special in the function called changeset/2.
I’m sorry, but I really don’t see a problem this is trying to solve. It’s, of course, different if you don’t use ecto, but if you do, I can’t see an advantage this offers.








