Auth Bypass in Hanami
How Auth Bypass Manifests in Hanami
Auth bypass in Hanami applications often stems from misconfigured action filters, missing authorization checks, or improper session handling. The framework's modular architecture, while flexible, can create subtle security gaps when authentication logic isn't consistently applied across all endpoints.
One common pattern involves actions that inherit from a base class but accidentally override or remove authentication filters. Consider this vulnerable structure:
class ApplicationController < Hanami::Action
before :authenticate_user
private
def authenticate_user
redirect_to '/login' unless session[:user_id]
end
end
class Dashboard::Show < ApplicationController
# Inherits authentication
end
class Public::Show < ApplicationController
skip_before :authenticate_user
# Now completely open
endThe skip_before call in Public::Show removes authentication entirely, potentially exposing sensitive data if the action name is misleading or reused incorrectly.
Another Hanami-specific vulnerability occurs with route constraints that don't align with authentication requirements. The framework allows defining constraints that might bypass middleware:
Hanami::Router.new do
get '/admin', to: Admin::Show
.constraints(format: 'json')
.middleware(AuthenticationMiddleware)
get '/admin', to: Admin::Show
.constraints(format: 'html')
# No middleware here!
endThis creates a situation where HTML requests to /admin bypass authentication entirely while JSON requests remain protected.
Session fixation attacks are particularly relevant in Hanami due to its Rack-based session handling. If session IDs aren't properly regenerated on login:
class Sessions::Create < Hanami::Action
def call(params)
user = UserRepository.new.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
# Missing: regenerate_session_id!
redirect_to '/dashboard'
else
self.status = 401
end
end
endAn attacker who knows or predicts session IDs can hijack authenticated sessions.
Hanami-Specific Detection
Detecting auth bypass in Hanami requires examining both the routing configuration and action filters systematically. Start by analyzing your config/routes.rb file for inconsistent middleware application:
routes = Hanami::Router.new do
# Check for routes without authentication middleware
get '/admin', to: Admin::Show
.constraints(accept: 'application/json')
# Verify this has proper auth
get '/settings', to: Settings::Show
# Is this protected?
endUse Hanami's built-in route inspection capabilities to audit all endpoints:
puts Hanami.app.router.routes.map do |route|
"#{route.request_method} #{route.path} -> #{route.action.class.name} (#{route.middleware.inspect})"
endLook specifically for routes that lack authentication middleware or have inconsistent middleware stacks.
Code review should focus on action inheritance patterns. Use this script to identify potentially vulnerable actions:
def find_unprotected_actions(app)
unprotected = []
app.actions.each do |action_class|
next if action_class == Hanami::Action
# Check if it inherits from ApplicationController
if action_class.ancestors.include?(ApplicationController)
# Look for skip_before calls or missing authentication
if action_class.instance_methods(false).include?(:before) == false
unprotected << action_class
end
end
end
unprotected
endAutomated scanning with middleBrick can identify auth bypass vulnerabilities by testing unauthenticated access to protected endpoints. The scanner attempts requests without session cookies or authentication headers and flags any successful access to endpoints that should require authentication:
$ middlebrick scan https://your-hanami-app.com
✓ Authentication bypass detected
Severity: High
Endpoint: POST /api/v1/users
Issue: Endpoint accepts unauthenticated requests
Recommendation: Add authentication middleware to this routemiddleBrick's black-box scanning approach is particularly effective for Hanami applications since it tests the actual runtime behavior without requiring source code access.
Hanami-Specific Remediation
Hanami provides several native mechanisms for robust authentication that prevent bypass vulnerabilities. The most reliable approach uses action filters consistently across your application:
class ApplicationController < Hanami::Action
before :authenticate!
private
def authenticate!
halt 401 unless authenticated?
end
def authenticated?
session[:user_id] && UserRepository.new.find(session[:user_id])
end
end
class Admin::Dashboard < ApplicationController
# Automatically protected
endFor routes that legitimately need to be public, create a separate base class to avoid inheritance mistakes:
class PublicApplicationController < Hanami::Action
# No authentication filters
end
class Public::Show < PublicApplicationController
# Explicitly public, cannot accidentally bypass auth
endImplement proper session management with ID regeneration:
class Sessions::Create < Hanami::Action
include Hanami::Action::Session
def call(params)
user = UserRepository.new.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session.regenerate_id
session[:user_id] = user.id
redirect_to '/dashboard'
else
self.status = 401
end
end
endHanami's middleware system allows consistent authentication across all routes. Configure it in config/application.rb:
middleware.use AuthenticationMiddleware
class AuthenticationMiddleware
def initialize(app)
@app = app
end
def call(env)
request = Rack::Request.new(env)
if protected_route?(request.path) && !authenticated?(request)
return [401, {}, ['Unauthorized']]
end
@app.call(env)
end
private
def protected_route?(path)
path.start_with?('/admin') || path.start_with?('/api')
end
def authenticated?(request)
request.session[:user_id]
end
endFor comprehensive protection, combine action-level filters with route-level middleware. This defense-in-depth approach ensures that even if one mechanism fails, the other provides protection.
middleBrick's continuous monitoring (Pro plan) can automatically scan your Hanami application on a schedule, alerting you if new auth bypass vulnerabilities are introduced:
$ middlebrick monitor --schedule=daily --threshold=80
Monitoring Hanami API...
✓ No auth bypass vulnerabilities detected
✓ Authentication coverage: 95% of endpoints
✓ Last scan: 2 hours agoThis proactive approach catches authentication regressions before they reach production.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |
Frequently Asked Questions
How can I verify that all my Hanami API endpoints are properly authenticated?
What's the difference between action filters and middleware for authentication in Hanami?
before :authenticate!) provide fine-grained control at the controller level and are specific to Hanami's action architecture. Middleware operates at the Rack level, affecting all requests before they reach your actions. For maximum security, use both: middleware for baseline protection and action filters for additional validation specific to your business logic.