This talk goes beyond classic security topics like XSS and CSRF, and focuses on how to defend Rails applications from real-world abuse and how Harvest leverages on the rack-attack gem to achive so
f lare, Stripe, and abuse engineering blogs “A bad actor is any human or automated system that intentionally abuses, misuses, or exploits an application to gain unauthorized access, cause disruption, or commit fraud”
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional Chaos monkey: means no harm Kinds of bad actors
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional Chaos monkey: means no harm Kinds of bad actors
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional Chaos monkey: means no harm Kinds of bad actors
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional Chaos monkey: means no harm Kinds of bad actors
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional Chaos monkey: means no harm Kinds of bad actors
use stolen credit cards 🎭 Scammers: impersonation 📣 Spammers: content or message f looding 🌩 DDoS: orchestrate attacks 🙈 Unintentional chaos monkey: means no harm Kinds of bad actors
request.env["rack.attack.throttle_data"] throttle_data.each do |name, data| Rails.logger.info "Throttle #{name} => #{data[:discriminator]}: #{data[:count]}/#{data[:limit]} (#{data[:period]}s)" end end end
request.env["rack.attack.throttle_data"] throttle_data.each do |name, data| Rails.logger.info "Throttle #{name} => #{data[:discriminator]}: #{data[:count]}/#{data[:limit]} (#{data[:period]}s)" end end end
request.env["rack.attack.throttle_data"] throttle_data.each do |name, data| Rails.logger.info "Throttle #{name} => #{data[:discriminator]}: #{data[:count]}/#{data[:limit]} (#{data[:period]}s)" end end end
request.path.starts_with?(“/v2/reports") discriminator = user_discriminator(request) "api-#{request.env['HTTP_HARVEST_ACCOUNT_ID']}-#{discriminator}" end end
request.path.starts_with?(“/v2/reports") discriminator = user_discriminator(request) "api-#{request.env['HTTP_HARVEST_ACCOUNT_ID']}-#{discriminator}" end end
request.path.starts_with?(“/v2/reports") discriminator = user_discriminator(request) "api-#{request.env['HTTP_HARVEST_ACCOUNT_ID']}-#{discriminator}" end end
name = "#{rule_name}/#{disc}" limit = proc { |request| ThrottlingRule.new(request, rule).limit(disc) } Rack::Attack.throttle(name, limit: limit, period: rule[:period]) do |request| conditions = ThrottlingRule.new(request, rule) if conditions.run conditions.get_discriminator(disc) end end end end
name = "#{rule_name}/#{disc}" limit = proc { |request| ThrottlingRule.new(request, rule).limit(disc) } Rack::Attack.throttle(name, limit: limit, period: rule[:period]) do |request| conditions = ThrottlingRule.new(request, rule) if conditions.run conditions.get_discriminator(disc) end end end end
name = "#{rule_name}/#{disc}" limit = proc { |request| ThrottlingRule.new(request, rule).limit(disc) } Rack::Attack.throttle(name, limit: limit, period: rule[:period]) do |request| conditions = ThrottlingRule.new(request, rule) if conditions.run conditions.get_discriminator(disc) end end end end
name = "#{rule_name}/#{disc}" limit = proc { |request| ThrottlingRule.new(request, rule).limit(disc) } Rack::Attack.throttle(name, limit: limit, period: rule[:period]) do |request| conditions = ThrottlingRule.new(request, rule) if conditions.run conditions.get_discriminator(disc) end end end end
name = "#{rule_name}/#{disc}" limit = proc { |request| ThrottlingRule.new(request, rule).limit(disc) } Rack::Attack.throttle(name, limit: limit, period: rule[:period]) do |request| conditions = ThrottlingRule.new(request, rule) if conditions.run conditions.get_discriminator(disc) end end end end
event.data.charge note = "Stripe #{charge.outcome.type} with risk score = #{charge.outcome.risk_score.to_i}” case charge.outcome.type when "blocked" company.flag_as_malicious(notes: note) when "manual_review" company.flag_as_suspicious(notes: note) end
event.data.charge note = "Stripe #{charge.outcome.type} with risk score = #{charge.outcome.risk_score.to_i}” case charge.outcome.type when "blocked" company.flag_as_malicious(notes: note) when "manual_review" company.flag_as_suspicious(notes: note) end
event.data.charge note = "Stripe #{charge.outcome.type} with risk score = #{charge.outcome.risk_score.to_i}” case charge.outcome.type when "blocked" company.flag_as_malicious(notes: note) when "manual_review" company.flag_as_suspicious(notes: note) end
event.data.charge note = "Stripe #{charge.outcome.type} with risk score = #{charge.outcome.risk_score.to_i}” case charge.outcome.type when "blocked" company.flag_as_malicious(notes: note) when "manual_review" company.flag_as_suspicious(notes: note) end
event.data.charge note = "Stripe #{charge.outcome.type} with risk score = #{charge.outcome.risk_score.to_i}” case charge.outcome.type when "blocked" company.flag_as_malicious(notes: note) when "manual_review" company.flag_as_suspicious(notes: note) end