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/xss/raw.ex
defmodule Sobelow.XSS.Raw do
alias Sobelow.Utils
use Sobelow.Finding
def run(fun, filename, web_root, controller) do
{vars, _, {fun_name, [{_, line_no}]}} = parse_render_def(fun)
web_root = if String.ends_with?(web_root, "/lib/") do
web_root <> Sobelow.get_env(:app_name) <> "/web/"
else
web_root
end
Enum.each vars, fn {template, ref_vars, vars} ->
template =
cond do
is_atom(template) -> Atom.to_string(template) <> ".html"
is_binary(template) -> template
true -> ""
end
template_path = web_root <> "templates/" <> controller <> "/" <> template <> ".eex"
if File.exists?(template_path) do
raw_vals = Utils.get_template_raw_vars(template_path)
Enum.each(ref_vars, fn var ->
if Enum.member?(raw_vals, var) do
# Sobelow.log_finding("XSS", :high)
t_name = String.replace_prefix(Path.expand(template_path, ""), "/", "")
add_finding(t_name, line_no, filename, fun_name, fun, var, :high)
end
end)
Enum.each(vars, fn var ->
if Enum.member?(raw_vals, var) do
# Sobelow.log_finding("XSS", :medium)
t_name = String.replace_prefix(Path.expand(template_path, ""), "/", "")
add_finding(t_name, line_no, filename, fun_name, fun, var, :medium)
end
end)
end
end
if String.ends_with?(filename, "_view.ex") do
{vars, params, {fun_name, [{_, line_no}]}} = parse_raw_def(fun)
Enum.each vars, fn var ->
if Enum.member?(params, var) || var === "conn.params" do
Sobelow.log_finding("XSS", :medium)
print_view_finding(line_no, filename, fun_name, fun, var, :medium)
else
Sobelow.log_finding("XSS", :low)
print_view_finding(line_no, filename, fun_name, fun, var, :low)
end
end
end
end
def parse_render_def(fun) do
{params, {fun_name, line_no}} = Utils.get_fun_declaration(fun)
pipefuns = Utils.get_pipe_funs(fun)
|> Enum.map(fn {_, _, opts} -> Enum.at(opts, 1) end)
|> Enum.flat_map(&Utils.get_funs_of_type(&1, :render))
pipevars = pipefuns
|> Enum.map(&Utils.parse_render_opts(&1, params, 0))
|> List.flatten
vars = Utils.get_funs_of_type(fun, :render) -- pipefuns
|> Enum.map(&Utils.parse_render_opts(&1, params, 1))
{vars ++ pipevars, params, {fun_name, line_no}}
end
def parse_raw_def(fun) do
Utils.get_fun_vars_and_meta(fun, 0, :raw)
end
def get_details() do
Sobelow.XSS.details()
end
defp add_finding(t_name, line_no, filename, fun_name, fun, var, severity) do
type = "XSS"
case Sobelow.format() do
"json" ->
finding = [
type: type,
file: filename,
function: "#{fun_name}:#{line_no}",
variable: "@#{var}",
template: "#{t_name}"
]
Sobelow.log_finding(finding, severity)
_ ->
Sobelow.log_finding(type, severity)
IO.puts Utils.finding_header(type, severity)
IO.puts Utils.finding_file_metadata(filename, fun_name, line_no)
IO.puts "Template: #{t_name} - @#{var}"
if Sobelow.get_env(:with_code), do: Utils.print_code(fun, var, :render)
IO.puts Utils.finding_break()
end
end
defp print_view_finding(line_no, filename, fun_name, fun, var, severity) do
Utils.add_finding(line_no, filename, fun,
fun_name, var, severity,
"XSS", :raw)
end
end