Brakeman Ruby auf Rails Security Scanner Cheat Sheet¶
Überblick¶
Brakeman ist ein statischer Analyse-Sicherheitssscanner speziell für Ruby auf Rails Anwendungen entwickelt. Es analysiert Rails Anwendungscode, um Sicherheitslücken zu finden, ohne dass die Anwendung ausgeführt werden muss. Brakeman ist ein wesentliches Werkzeug in DevSecOps Pipelines für Rails-Anwendungen und hilft Entwicklern, gemeinsame Sicherheitsprobleme wie SQL-Injektion, Cross-Site-Skripting (XSS) und andere Rails-spezifische Schwachstellen frühzeitig im Entwicklungsprozess zu identifizieren.
ZEIT Note: Brakeman ist speziell für Ruby auf Rails-Anwendungen konzipiert und kann nicht korrekt mit anderen Ruby-Frameworks arbeiten. Es sollte als Teil einer umfassenden Sicherheitsteststrategie verwendet werden.
Installation¶
Edelstein verwenden¶
```bash
Install Brakeman gem¶
gem install brakeman
Install specific version¶
gem install brakeman -v 5.4.1
Install from source¶
git clone https://github.com/presidentbeef/brakeman.git cd brakeman gem build brakeman.gemspec gem install brakeman-*.gem
Verify installation¶
brakeman --version ```_
Mit Bundler¶
```ruby
Add to Gemfile¶
group :development do gem 'brakeman', require: false end
Install¶
bundle install
Run via bundle¶
bundle exec brakeman ```_
Verwendung von Docker¶
```bash
Pull official Brakeman image¶
docker pull presidentbeef/brakeman
Run Brakeman in container¶
docker run --rm -v $(pwd):/code presidentbeef/brakeman
Build custom image¶
cat > Dockerfile ``<< 'EOF' FROM ruby:3.0-slim RUN gem install brakeman WORKDIR /app ENTRYPOINT ["brakeman"] EOF
docker build -t custom-brakeman . docker run --rm -v $(pwd):/app custom-brakeman ```_
Paketmanager¶
```bash
Ubuntu/Debian (via RubyGems)¶
sudo apt update sudo apt install ruby-dev sudo gem install brakeman
macOS with Homebrew¶
brew install brakeman
CentOS/RHEL/Fedora¶
sudo dnf install ruby-devel sudo gem install brakeman ```_
Basisnutzung¶
Einfache Scans¶
```bash
Scan current Rails application¶
brakeman
Scan specific Rails application¶
brakeman /path/to/rails/app
Scan with verbose output¶
brakeman -v
Scan with debug output¶
brakeman -d
Quick scan (faster, less thorough)¶
brakeman -q
Scan specific files¶
brakeman --only-files app/controllers/users_controller.rb,app/models/user.rb ```_
Ausgabeformate¶
```bash
Default text output¶
brakeman
JSON output¶
brakeman -f json
HTML output¶
brakeman -f html
CSV output¶
brakeman -f csv
Markdown output¶
brakeman -f markdown
SARIF output (for GitHub integration)¶
brakeman -f sarif
Save output to file¶
brakeman -o brakeman-report.html -f html brakeman -o brakeman-report.json -f json brakeman -o brakeman-report.csv -f csv ```_
Sicherheitsstufen¶
```bash
Show only high confidence warnings¶
brakeman -w3
Show high and medium confidence warnings¶
brakeman -w2
Show all warnings (including low confidence)¶
brakeman -w1
Default behavior (medium and high confidence)¶
brakeman ```_
Konfiguration¶
Konfigurationsdatei (.brakeman.yml)¶
```yaml
.brakeman.yml¶
:app_path: "." :output_files: - "brakeman-report.html" - "brakeman-report.json" :output_formats: - :html - :json :quiet: false :min_confidence: 2 :combine_locations: true :collapse_mass_assignment: true :highlight_user_input: true :ignore_redirect_to_model: true :ignore_model_output: false :check_arguments: true :safe_methods: - :sanitize - :h - :html_escape :skip_checks: - :SSL - :LinkTo :report_progress: true :parallel_checks: true ```_
Konfiguration der Befehlszeile¶
```bash
Set minimum confidence level¶
brakeman --confidence-level 2 # Medium and high only brakeman --confidence-level 3 # High only
Skip specific checks¶
brakeman --skip-checks SSL,LinkTo,Render
Run only specific checks¶
brakeman --test SQL,XSS,Command
Ignore specific files¶
brakeman --skip-files app/controllers/admin_controller.rb
Set Rails version explicitly¶
brakeman --rails3 brakeman --rails4 brakeman --rails5 brakeman --rails6 brakeman --rails7
Additional options¶
brakeman --no-progress # Disable progress reporting brakeman --no-pager # Disable pager for output brakeman --table-width 120 # Set table width brakeman --url-safe-methods method1,method2 # Additional URL-safe methods ```_
Erweiterte Nutzung¶
Baseline und Progressive Scanning¶
```bash
Create baseline¶
brakeman -f json -o baseline.json
Compare against baseline¶
brakeman --compare baseline.json
Ignore baseline warnings¶
brakeman --ignore-config baseline.ignore
Generate ignore file from current warnings¶
brakeman --ignore-config brakeman.ignore --interactive-ignore ```_
Zollkontrollen¶
```ruby
custom_check.rb¶
class CustomCheck < Brakeman::BaseCheck Brakeman::Checks.add self
@description = "Check for custom security pattern"
def run_check tracker.find_call(:target =>`` nil, :method => :dangerous_method).each do|result| warn :result => result, :warning_type => "Custom Warning", :warning_code => :custom_dangerous_method, :message => "Avoid using dangerous_method", :confidence => :high end end end ```_
Integration mit Schienen¶
```ruby
config/brakeman.yml in Rails app¶
:app_path: "." :output_files: - "tmp/brakeman-report.html" :output_formats: - :html :quiet: true :min_confidence: 2
Rake task integration¶
lib/tasks/security.rake¶
namespace :security do desc "Run Brakeman security scan" task :scan do require 'brakeman'
options = \\\\{
:app_path => Rails.root.to_s,
:output_formats => [:html, :json],
:output_files => [
Rails.root.join('tmp', 'brakeman-report.html').to_s,
Rails.root.join('tmp', 'brakeman-report.json').to_s
],
:quiet => false,
:min_confidence => 2
\\\\}
tracker = Brakeman.run(options)
if tracker.warnings.any?
puts "Security warnings found! Check tmp/brakeman-report.html"
exit 1
else
puts "No security warnings found."
end
end end ```_
CI/CD Integration¶
GitHub Aktionen¶
```yaml
.github/workflows/security.yml¶
name: Security Scan
on: [push, pull_request]
jobs: brakeman: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- name: Install Brakeman
run: gem install brakeman
- name: Run Brakeman
run: brakeman -f sarif -o brakeman-results.sarif
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: brakeman-results.sarif
- name: Upload results
uses: actions/upload-artifact@v3
with:
name: brakeman-report
path: brakeman-results.sarif
```_
GitLab CI¶
```yaml
.gitlab-ci.yml¶
stages: - security
brakeman: stage: security image: ruby:3.0 before_script: - gem install brakeman script: - brakeman -f json -o brakeman-report.json artifacts: reports: sast: brakeman-report.json paths: - brakeman-report.json expire_in: 1 week allow_failure: true ```_
Jenkins Pipeline¶
```groovy // Jenkinsfile pipeline \\{ agent any
stages \\\\{
stage('Security Scan') \\\\{
steps \\\\{
script \\\\{
sh 'gem install brakeman'
sh 'brakeman -f json -o brakeman-report.json'
sh 'brakeman -f html -o brakeman-report.html'
\\\\}
\\\\}
post \\\\{
always \\\\{
archiveArtifacts artifacts: 'brakeman-report.*', fingerprint: true
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: '.',
reportFiles: 'brakeman-report.html',
reportName: 'Brakeman Security Report'
])
\\\\}
failure \\\\{
emailext (
subject: "Security Scan Failed: $\\\\{env.JOB_NAME\\\\} - $\\\\{env.BUILD_NUMBER\\\\}",
body: "Brakeman found security issues. Check the report for details.",
to: "$\\\\{env.CHANGE_AUTHOR_EMAIL\\\\}"
)
\\\\}
\\\\}
\\\\}
\\\\}
\\} ```_
Kreis¶
```yaml
.circleci/config.yml¶
version: 2.1
jobs: security_scan: docker: - image: cimg/ruby:3.0 steps: - checkout - run: name: Install Brakeman command: gem install brakeman - run: name: Run Brakeman command:| brakeman -f json -o brakeman-report.json brakeman -f html -o brakeman-report.html - store_artifacts: path: brakeman-report.html - store_artifacts: path: brakeman-report.json
workflows: version: 2 security: jobs: - security_scan ```_
Gemeinsame Schwachstelle Muster¶
SQL Injection¶
```ruby
BAD: String interpolation in queries¶
User.where("name = '#\\{params[:name]\\}'") User.find_by_sql("SELECT * FROM users WHERE id = #\\{params[:id]\\}")
GOOD: Parameterized queries¶
User.where(name: params[:name]) User.where("name = ?", params[:name]) User.find_by_sql(["SELECT * FROM users WHERE id = ?", params[:id]]) ```_
Cross-Site Scripting (XSS)¶
```erb
<%= params[:message] %> <%= raw user_input %> <%= content.html_safe %>
<%= h(params[:message]) %> <%= sanitize(user_input) %> <%= simple_format(content) %> ```_
Massenzuweisung¶
```ruby
BAD: Unfiltered parameters¶
User.create(params[:user]) user.update_attributes(params[:user])
GOOD: Strong parameters¶
def user_params params.require(:user).permit(:name, :email) end
User.create(user_params) user.update_attributes(user_params) ```_
Befehlsinjektion¶
```ruby
BAD: Unescaped system calls¶
system("ls #\\{params[:directory]\\}")
grep #\\{params[:pattern]\\} file.txt
GOOD: Escaped or parameterized calls¶
system("ls", params[:directory]) Open3.capture3("grep", params[:pattern], "file.txt") ```_
Cross-Site Request Forgery (CSRF)¶
```ruby
BAD: Missing CSRF protection¶
class ApplicationController ``< ActionController::Base # protect_from_forgery commented out end
GOOD: CSRF protection enabled¶
class ApplicationController < ActionController::Base protect_from_forgery with: :exception end ```_
Automatisierung und Schrift¶
Automatischer Sicherheitsscanner¶
```ruby
!/usr/bin/env ruby¶
brakeman_scanner.rb¶
require 'brakeman' require 'json' require 'optparse'
class BrakemanScanner def initialize(app_path, options = \{\}) @app_path = app_path @options = \{ app_path: app_path, quiet: true, min_confidence: 2, output_formats: [:json, :html], output_files: [ File.join(app_path, 'tmp', 'brakeman-report.json'), File.join(app_path, 'tmp', 'brakeman-report.html') ] \}.merge(options) end
def run_scan puts "Running Brakeman scan on #\{@app_path\}..."
begin
@tracker = Brakeman.run(@options)
generate_summary
return @tracker.warnings.empty?
rescue =>`` e
puts "Error running Brakeman: #\\\\{e.message\\\\}"
return false
end
end
def generate_summary warnings = @tracker.warnings
puts "\n=== Brakeman Security Scan Summary ==="
puts "Total warnings: #\\\\{warnings.length\\\\}"
# Group by confidence
by_confidence = warnings.group_by(&:confidence)
puts "High confidence: #\\\\{(by_confidence[:high]||[]).length\\\\}"
puts "Medium confidence: #\\\\{(by_confidence[:medium]||[]).length\\\\}"
puts "Low confidence: #\\\\{(by_confidence[:low]||[]).length\\\\}"
# Group by warning type
by_type = warnings.group_by(&:warning_type)
puts "\nWarnings by type:"
by_type.each do|type, type_warnings|
puts " #\\\\{type\\\\}: #\\\\{type_warnings.length\\\\}"
end
# Show high confidence warnings
high_warnings = by_confidence[:high]||[]
if high_warnings.any?
puts "\n=== High Confidence Warnings ==="
high_warnings.each do|warning|
puts "#\\\\{warning.file\\\\}:#\\\\{warning.line\\\\} - #\\\\{warning.warning_type\\\\}: #\\\\{warning.message\\\\}"
end
end
end
def save_baseline baseline_file = File.join(@app_path, 'brakeman.baseline') File.write(baseline_file, @tracker.warnings.to_json) puts "Baseline saved to #\\{baseline_file\\}" end
def compare_with_baseline baseline_file = File.join(@app_path, 'brakeman.baseline') return unless File.exist?(baseline_file)
baseline_warnings = JSON.parse(File.read(baseline_file))
current_warnings = @tracker.warnings.map(&:to_hash)
new_warnings = current_warnings - baseline_warnings
fixed_warnings = baseline_warnings - current_warnings
puts "\n=== Baseline Comparison ==="
puts "New warnings: #\\\\{new_warnings.length\\\\}"
puts "Fixed warnings: #\\\\{fixed_warnings.length\\\\}"
if new_warnings.any?
puts "\nNew warnings found:"
new_warnings.each do|warning|
puts " #\\\\{warning['file']\\\\}:#\\\\{warning['line']\\\\} - #\\\\{warning['warning_type']\\\\}"
end
end
end end
Command line interface¶
options = \\{\\} OptionParser.new do|opts| opts.banner = "Usage: #\\{$0\\} [options] [app_path]"
opts.on("-c", "--confidence LEVEL", Integer, "Minimum confidence level (1-3)") do|c| options[:min_confidence] = c end
opts.on("-q", "--quiet", "Quiet mode") do options[:quiet] = true end
opts.on("-b", "--baseline", "Save current scan as baseline") do options[:save_baseline] = true end
opts.on("--compare", "Compare with baseline") do options[:compare_baseline] = true end
opts.on("-h", "--help", "Show this help") do puts opts exit end end.parse!
app_path = ARGV[0]||Dir.pwd
scanner = BrakemanScanner.new(app_path, options) success = scanner.run_scan
if options[:save_baseline] scanner.save_baseline end
if options[:compare_baseline] scanner.compare_with_baseline end
exit(success ? 0 : 1) ```_
Batch Processing Script¶
```bash
!/bin/bash¶
batch_brakeman_scan.sh¶
Configuration¶
RAILS_APPS_DIR="/path/to/rails/apps" REPORTS_DIR="/path/to/reports" DATE=$(date +%Y%m%d_%H%M%S)
Create reports directory¶
mkdir -p "$REPORTS_DIR"
Function to scan Rails app¶
scan_rails_app() \\{ local app_path="\(1" local app_name=\)(basename "\(app_path") local report_file="\)REPORTS_DIR/\(\\\\{app_name\\\\}_\)\\{DATE\\}.json" local html_report="\(REPORTS_DIR/\)\\{app_name\\}_$\\{DATE\\}.html"
echo "Scanning $app_name..."
# Check if it's a Rails app
if [ ! -f "$app_path/config/application.rb" ]; then
echo "Skipping $app_name - not a Rails application"
return
fi
# Run Brakeman scan
cd "$app_path"
brakeman -f json -o "$report_file" -q
brakeman -f html -o "$html_report" -q
# Check for high confidence warnings
high_warnings=$(jq '[.warnings[]|select(.confidence == "High")]|length' "$report_file" 2>/dev/null||echo "0")
if [ "$high_warnings" -gt 0 ]; then
echo "WARNING: $app_name has $high_warnings high confidence warnings!"
echo "$app_name" >> "$REPORTS_DIR/high_risk_apps.txt"
fi
echo "Scan completed for $app_name"
\\}
Find and scan all Rails applications¶
find "\(RAILS_APPS_DIR" -name "application.rb" -path "*/config/*"|while read -r config_file; do app_dir=\)(dirname "\((dirname "\)config_file")") scan_rails_app "$app_dir" done
echo "Batch scanning completed. Reports saved to $REPORTS_DIR"
Generate summary report¶
echo "=== Batch Scan Summary ===" > "\(REPORTS_DIR/summary_\)\\{DATE\\}.txt" echo "Scan Date: \((date)" >> "\)REPORTS_DIR/summary_\(\\\\{DATE\\\\}.txt" echo "Total applications scanned: \((find "\)REPORTS_DIR" -name "*_\)\\{DATE\\}.json"|wc -l)" >> "\(REPORTS_DIR/summary_\)\\{DATE\\}.txt"
if [ -f "\(REPORTS_DIR/high_risk_apps.txt" ]; then echo "High risk applications: \((wc -l < "\)REPORTS_DIR/high_risk_apps.txt")" >> "\)REPORTS_DIR/summary_\(\\\\{DATE\\\\}.txt" echo "" >> "\)REPORTS_DIR/summary_\(\\\\{DATE\\\\}.txt" echo "High risk applications:" >> "\)REPORTS_DIR/summary_\(\\\\{DATE\\\\}.txt" cat "\)REPORTS_DIR/high_risk_apps.txt" >> "\(REPORTS_DIR/summary_\)\\{DATE\\}.txt" fi ```_
Integration in Entwicklungswerkzeuge¶
VS Code Integration¶
```json // .vscode/tasks.json \\{ "version": "2.0.0", "tasks": [ \\{ "label": "Brakeman Security Scan", "type": "shell", "command": "brakeman", "args": ["-f", "html", "-o", "tmp/brakeman-report.html"], "group": "test", "presentation": \\{ "echo": true, "reveal": "always", "focus": false, "panel": "shared" \\}, "problemMatcher": [] \\} ] \\}
// .vscode/settings.json \\{ "ruby.lint": \\{ "brakeman": \\{ "enable": true, "command": "brakeman" \\} \\} \\} ```_
RubyMine Integration¶
```bash
External tool configuration¶
Program: brakeman¶
Arguments: -f html -o \(ProjectFileDir\)/tmp/brakeman-report.html¶
Working directory: \(ProjectFileDir\)¶
```_
Integration von Schutzmaßnahmen¶
```ruby
Guardfile¶
guard :brakeman, :run_on_start => true do watch(%r\\{^app/.+.(rb|erb)\(\\\\}) watch(%r\\\\{^config/.+\.rb\)\\}) watch(%r\\{^lib/.+.rb$\\}) watch('Gemfile') end ```_
Best Practices¶
Konfigurationsmanagement¶
```yaml
.brakeman.yml - Production configuration¶
:app_path: "." :output_files: - "tmp/brakeman-report.html" - "tmp/brakeman-report.json" :output_formats: - :html - :json :quiet: false :min_confidence: 2 :combine_locations: true :collapse_mass_assignment: true :highlight_user_input: true :ignore_redirect_to_model: true :ignore_model_output: false :check_arguments: true :safe_methods: - :sanitize - :h - :html_escape - :simple_format :skip_checks: [] :report_progress: true :parallel_checks: true :absolute_paths: false :summary_only: false ```_
Ignorieren von Dateimanagement¶
```yaml
brakeman.ignore¶
:ignored_warnings: - :warning_type: SQL :fingerprint: 1234567890abcdef :note: "Reviewed and accepted - admin only functionality" - :warning_type: CrossSiteScripting :fingerprint: abcdef1234567890 :note: "False positive - output is properly sanitized" ```_
Teamworkflow¶
```bash
Makefile integration¶
.PHONY: security-scan security-scan: @echo "Running Brakeman security scan..." @brakeman -q -f json -o tmp/brakeman-report.json @if [ -s tmp/brakeman-report.json ]; then \ echo "Security warnings found! Check tmp/brakeman-report.html"; \ brakeman -f html -o tmp/brakeman-report.html; \ exit 1; \ else \ echo "No security warnings found."; \ fi
.PHONY: security-baseline security-baseline: @echo "Creating security baseline..." @brakeman -f json -o brakeman.baseline @echo "Baseline created. Commit brakeman.baseline to version control."
Pre-commit hook¶
!/bin/bash¶
.git/hooks/pre-commit¶
echo "Running Brakeman security scan..." brakeman -q --no-pager if [ $? -ne 0 ]; then echo "Security issues found. Commit aborted." echo "Run 'brakeman' to see details or 'brakeman -I' to ignore warnings." exit 1 fi ```_
Fehlerbehebung¶
Gemeinsame Themen¶
```bash
Issue: Brakeman not detecting Rails app¶
Solution: Ensure you're in Rails root directory¶
cd /path/to/rails/app ls config/application.rb # Should exist
Issue: Too many false positives¶
Solution: Use ignore file and tune confidence levels¶
brakeman --confidence-level 3 # High confidence only brakeman -I # Interactive ignore mode
Issue: Performance issues with large apps¶
Solution: Use parallel processing and skip unnecessary checks¶
brakeman --parallel-checks --skip-checks Render,LinkTo
Issue: Integration with CI/CD failing¶
Solution: Use appropriate exit codes and formats¶
brakeman -q -f json -o results.json||true ```_
Leistungsoptimierung¶
```bash
Skip time-consuming checks¶
brakeman --skip-checks Render,LinkTo,DetailedExceptions
Use parallel processing¶
brakeman --parallel-checks
Scan only specific directories¶
brakeman --only-files app/controllers/,app/models/
Quick scan mode¶
brakeman -q --faster ```_
Debugging¶
```bash
Debug mode¶
brakeman -d
Verbose output¶
brakeman -v
Show timing information¶
brakeman --timing
Test specific warning types¶
brakeman --test SQL,XSS ```_
Ressourcen¶
- (LINK_5_)
- Brakeman GitHub Repository
- (LINK_5)
- (LINK_5)
- (LINK_5_)
--
*Dieses Betrugsblatt bietet umfassende Anleitung für die Verwendung von Brakeman, um Sicherheitslücken in Ruby auf Rails Anwendungen zu identifizieren. Kombinieren Sie immer statische Analyse mit anderen Sicherheitstestmethoden für eine umfassende Deckung. *