Packages
sobelow
0.4.1
0.14.1
0.14.0
0.13.0
0.12.2
0.12.1
0.12.0
0.11.1
0.11.0
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
Security-focused static analysis for Elixir & the Phoenix framework
Current section
Files
Jump to
Current section
Files
lib/sobelow/traversal/send_file.ex
defmodule Sobelow.Traversal.SendFile do
alias Sobelow.Utils
use Sobelow.Finding
def run(fun, filename) do
severity = if String.ends_with?(filename, "_controller.ex"), do: false, else: :low
# If the file is a controller, check for `send_file` as well as
# `Plug.Conn.send_file`. If it is not a controller, look for
# `Plug.Conn.send_file` only.
if String.ends_with?(filename, "_controller.ex") do
{vars, params, {fun_name, [{_, line_no}]}} = parse_send_file_def(fun)
Enum.each vars, fn var ->
if Enum.member?(params, var) || var === "conn.params" do
# Sobelow.log_finding("Directory Traversal", severity || :high)
print_finding(line_no, filename, fun_name, fun, var, severity || :high)
else
# Sobelow.log_finding("Directory Traversal", severity || :medium)
print_finding(line_no, filename, fun_name, fun, var, severity || :medium)
end
end
else
{vars, params, {fun_name, [{_, line_no}]}} = parse_aliased_send_file_def(fun)
Enum.each vars, fn var ->
if Enum.member?(params, var) || var === "conn.params" do
print_finding(line_no, filename, fun_name, fun, var, severity || :high)
else
print_finding(line_no, filename, fun_name, fun, var, severity || :medium)
end
end
end
end
## send_file(conn, status, file, offset \\ 0, length \\ :all)
##
## send_file has optional params, so the parameter we care about
## for traversal won't be at a definite location. This is a
## simple solution to the problem.
defp parse_send_file_def(fun) do
{files, params, {fun_name, line_no}} = Utils.get_fun_vars_and_meta(fun, 2, :send_file)
{aliased_files,_,_} = Utils.get_fun_vars_and_meta(fun, 2, :send_file, [:Plug, :Conn])
{files ++ aliased_files, params, {fun_name, line_no}}
end
defp parse_aliased_send_file_def(fun) do
Utils.get_fun_vars_and_meta(fun, 2, :send_file, [:Plug, :Conn])
end
def print_finding(line_no, filename, fun_name, fun, var, severity) do
Utils.add_finding(line_no, filename, fun,
fun_name, var, severity,
"Directory Traversal in `send_file`", :send_file, [:Plug, :Conn])
end
def get_details() do
Sobelow.Traversal.details()
end
end