Brakeman est un scanner de vulnérabilité pour application Ruby On Rails.
Utilisation:
$ brakeman /path/to/rubyapp
ressource:
Structure d'un projet RoR
.
├── Dockerfile #software version, hardcoded credentials
├── Gemfile #software versions
├── Gemfile.lock #software versions
├── app
│ ├── assets # images, video etc
│ ├── controllers #all application logic located here
│ │ ├── admin_controller.rb
│ │ ├── users_controller.rb
│ ├── helpers #helper - method that is (mostly) used to share reusable code
│ │ ├── admin_helper.rb
│ ├── mailers #allows send emails from your application using mailer classes
│ │ └── user_mailer.rb
│ ├── models #Ruby class that is used to represent data
│ │ ├── user.rb
│ └── views # HTML templates
│ ├── admin
│ │ ├── get_all_users.html.erb
├── config #app configuration, should be reviewed because developers can disable security features
│ ├── application.rb #application configuration
│ ├── boot.rb
│ ├── database.yml #database config, may contain hard-coded creds
│ ├── environment.rb
│ ├── environments
│ │ ├── development.rb #application configuration
│ ├── initializers
│ │ ├── constants.rb #hardcoded credentials
│ │ ├── filter_parameter_logging.rb #logging
│ │ ├── html_entities.rb #Enables or disables the escaping of HTML entities in JSON serialization
│ │ ├── key.rb #hardcoded credentials
│ │ ├── secret_token.rb #cookie signing
│ │ ├── session_store.rb #how session store is organized
│ ├── locales
│ │ └── en.yml #hardcoded credentials
│ ├── routes.rb #First thing to investigate, application routing
│ ├── secrets.yml #Is credentials/secrets encrypted?
│ └── secrets2.yml #Is credentials/secrets encrypted?
├── db
│ ├── schema.rb #database schema
│ └── seeds.rb #database data, may contain hard-coded creds
├── lib #extended modules
│ ├── encryption.rb #encryption
├── log #log files
├── public #static files and compiled assets
│ ├── 404.html
│ └── robots.txt
├── script
├── spec #for testing purposes
└── vendor #third-party code
Points d'interet
/config/database.yml - Peut contenir des identifiants de production
/config/initializers/secret_token.rb - Contient les secrets utilisés pour hash les cookies
/db/seeds.rb - Peut contenir des données de départ, y compris l'utilisateur administrateur bootstrap.
/db/development.sqlite3 - Peut contenir des données sensibles
Routing
Permet de mapper des routes avec ses gestionnaires pour comprendre la structure API de l'application. Le routeur détermine quel type de contrôleur et d'action doit réellement exécuter le code. Le routage des applications est décrit dans le fichier /config/routes.rb.
ressources:
Controllers
Views
Les vues sont stockées dans le chemin de modèle suivant:
app/views/[controller]/[view_name].html.erb
Une vue est une simple page HTML gérée par le moteur de modèle ERB, qui affiche les valeurs renvoyées par le contrôleur.
Models
Un modèle est une classe Ruby utilisée pour représenter des données. De plus, les modèles peuvent interagir avec la base de données de l'application via une fonctionnalité de Rails appelée Active Record.
Les environnements doivent utiliser une clé aléatoire présente dans config/credentials.yml.enc et la clé doit être chiffrée.
Mass assignement
Whitelist_attributes doit être sur false:
config.active_record.whitelist_attributes=false
Tout paramètre peut être utilisé lors d’un appel de mass assignment lorsque .permit! est utilisé.
Exemple:
def create
user = User.new(user_params)
...
...
def user_params
params.require(:user).permit!
end
Permet ceci,
User.new(
:email => "email@email.com",
:admin => "true", # Or la valeur de admin ne devrait pas être modifiable
:password => "password",
:first_name => "John",
:last_name => "Doe"
)
XSS
Si ActiveSupport::escape_html_entities_in_json = false :
to_json() = potentielle XSS
RoR échape le code html par défaut mais certaines méthode dépréciées permettent d'outrepasser cette protection:
raw
html_save
content_tag
Exemples
html = "<div>#{name}</div>".html_safe
content_tag :p, "Hello, #{name}”
raw @user.name
Contourner le moteur de template:
ERB.new("<div>#{@user.name}</div>").result
render inline: "<div>#{@user.name}</div>”
render text: "<div>#{@user.name}</div>”
Variables explicitements unescaped:
<%= name.html_safe %>
<%= content_tag :p, "Hello, #{name}" %>
<%= raw @user.name =>
<%== @user.name %>
Template placé à un endroit dangereux:
<div class=<%= classes %></div>
<a href="<%= link %>"></a>
<%= link_to "Here", @link %>
<script>var name = <%= name %>;</script>
OS injection
eval("ruby code here")
system("os command here")
`ls -al /` # (backticks contain os command)
exec("os command here")
spawn("os command here")
open("| os command here")
URI#open from open-uri
Process.exec("os command here")
Process.spawn("os command here")
IO.binread("| os command here")
IO.binwrite("| os command here", "foo")
IO.foreach("| os command here") {}
IO.popen("os command here")
IO.read("| os command here")
IO.readlines("| os command here")
IO.write("| os command here", "foo")
syscall
%x() %x %x{} %x-os-
popen<n>
exec
Open3.popen3()
fork()
PTY.spawn()
constantize
SQLi
La concaténation de l'entrée utilisateur avec le paramètre de requête SQL peut entraîner une injection SQL.