Rails Against the Machine | Rubyconf MY 2018

Rails Against the Machine | Rubyconf MY 2018

What should a development team do when a few bad users threaten their application? Online businesses are plagued with trolls, swindlers and con artists. In this talk, learn how your team can leverage features from RoR and Amazon Web Services to monitor and (secretly) segment bad actors using automation and behavioral triggers. If you work on a site with valuable users worth protecting, this talk is for you.

D82778274a818df1c0379d1453462e3f?s=128

Brittany Martin

October 25, 2018
Tweet

Transcript

  1. Rails Against the Machine Brittany Martin Rubyconf MY 2018 @brittjmartin

  2. Lead Web Developer @ Pittsburgh Cultural Trust ARTS E- COMMERCE

    TEN BRANDED PATHS FESTIVAL GUIDES ALL LOVINGLY BUILT WITH RUBY @brittjmartin
  3. HOSTING EMAIL PROVIDER E-COMMERCE CALL CENTER VISUAL ARTS My experience.

    @brittjmartin
  4. Norma Skates @ Little Steel Derby Girls @brittjmartin

  5. Host of the 5 by 5 Ruby on Rails Podcast

    @brittjmartin
  6. An ideal world. @brittjmartin

  7. In reality. @brittjmartin

  8. Gaming the site. Milking the system. Bending the rules. @brittjmartin

  9. Bad users. @brittjmartin

  10. Manipulation vs. Security. Photo Credit: Moz @brittjmartin

  11. Misbehaving. @brittjmartin

  12. Photo Credit: NFL @brittjmartin

  13. Identify. Photo Credit: Disney @brittjmartin

  14. PERSONAS Ask questions. CUSTOMER SUPPORT LOGS @brittjmartin

  15. “Bad user” examples. @brittjmartin Photo Credit: Dizinga

  16. Photo Credit: Tone Deaf Ticket resellers. @brittjmartin

  17. An American musical. $10.5m. 30 shows. @brittjmartin

  18. Serial returners. @brittjmartin

  19. @brittjmartin Upvote Rings

  20. Profit loss. Lost relationships. Inflation. @brittjmartin

  21. Strategy. @brittjmartin

  22. Choice 2: Quietly degrade. Choice 1: Kick them out. @brittjmartin

  23. Subtlety is key. @brittjmartin

  24. Automation. @brittjmartin

  25. Our tool belt. @brittjmartin

  26. @brittjmartin

  27. @brittjmartin Photo Credit: Choice

  28. @brittjmartin

  29. Define a model. @brittjmartin

  30. class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0

    def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end
  31. Mark them. @brittjmartin

  32. class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0

    def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end
  33. def authenticate_the_user authenticate_credentials do |result| result.success { remember_current_user reseller_cookie register_new_reseller

    head :ok } result.fail { error_message = 'The username or password entered is invalid. Please try again.' head :bad_request, :ErrorMsg => error_message } end end
  34. Offload. @brittjmartin

  35. class CatchNewResellerWorker include Sidekiq::Worker RESELLER_CONSTITUENCY = 223 def perform(hash) id

    = hash[‘id’] response = TessituraRest.new.create_constituencies(RESELLER_CONSTITUENCY, id) ResellerAlertWorker.perform_async(id: id) end end
  36. class ResellerAlertWorker include Sidekiq::Worker def perform(hash={}) notification = { 'username':

    'resellerbot', 'icon_emoji': ':skull:', 'fields': [ { 'title': 'Id', 'value': "#{hash['id']}" }, { 'title': 'Alert', 'value': 'Another reseller has been located and tagged!' } ] } RESELLER.ping notification end end slack- notifier.
  37. None
  38. Cache the check. @brittjmartin

  39. class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0

    def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end
  40. Who’s there? @brittjmartin

  41. Logged in. @brittjmartin

  42. Entice them. @brittjmartin

  43. Anonymous. @brittjmartin

  44. C is for cookie. @brittjmartin

  45. @brittjmartin Execute.

  46. @brittjmartin What can we take away?

  47. Select your own seat. @brittjmartin

  48. @brittjmartin Print at home.

  49. @brittjmartin Exchanges.

  50. @brittjmartin Degrading the experience.

  51. @brittjmartin

  52. @brittjmartin

  53. @brittjmartin

  54. @brittjmartin

  55. Web application firewall. @brittjmartin WAF.

  56. Block, allow, count. Join & reuse. Rules. @brittjmartin

  57. @brittjmartin

  58. GuardDuty. @brittjmartin

  59. @brittjmartin

  60. @brittjmartin Remember.

  61. Logo Credit: Mortal Kombat @brittjmartin

  62. Photo Credit: Pittsburgh Cultural Trust @brittjmartin

  63. Twitter: @brittjmartin Github: @wonderwoman13 Podcast: http://5by5.tv/rubyonrails