Slide 1

Slide 1 text

©2018 Wantedly, Inc. RailsηΩϡϦςΟΨΠυΛ վΊͯಡΜͰΈͨ 29.July.2018 - Hazumi Ichijo (@rerost) ৽ଔΤϯδχΞ͕վΊͯಡΜͰΈͯ

Slide 2

Slide 2 text

©2018 Wantedly, Inc. ࣗݾ঺հ Ұᑍ୺੅ (Twitter: @hazumirr, Github: @rerost) Web Application Engineer Rails, React, … ۴࿏ߴઐ -> ஜ೾େֶ -> Wantedly

Slide 3

Slide 3 text

©2018 Wantedly, Inc. Page Subtitle https://railsguides.jp/security.html

Slide 4

Slide 4 text

©2018 Wantedly, Inc. 1. ීஈ͔ΒؾΛ͚͍ͭͨ͜ͱ • ϦμΠϨΫτ • ਖ਼نදݱ • nilνΣοΫෆ଍ • XSS ͳͲ 2. ࣄલʹ๷͍Ͱ͓͖͍ͨ෦෼ • ηογϣϯݻఆ߈ܸ • CSRF ͳͲ RailsηΩϡϦςΟΨΠυ

Slide 5

Slide 5 text

©2018 Wantedly, Inc. 1. ීஈ͔ΒؾΛ͚͍ͭͨ͜ͱ • ϦμΠϨΫτ • ਖ਼نදݱ • nilνΣοΫෆ଍ • XSS ͳͲ 2. ࣄલʹ๷͍Ͱ͓͖͍ͨ෦෼ • ηογϣϯݻఆ߈ܸ • CSRF ͳͲ RailsηΩϡϦςΟΨΠυ ࠓ೔͸ͬͪ͜

Slide 6

Slide 6 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ def legacy redirect_to(params.update(action:'main')) end https://railsguides.jp/security.html#ϦμΠϨΫτ

Slide 7

Slide 7 text

©2018 Wantedly, Inc. ϦμΠϨΫτ def legacy redirect_to(params.update(action:'main')) end http://www.example.com/site/legacy? param1=xy¶m2=23&host=www.attacker.com https://railsguides.jp/security.html#ϦμΠϨΫτ

Slide 8

Slide 8 text

©2018 Wantedly, Inc. ϦμΠϨΫτ def legacy redirect_to(params.update(action:'main')) end https://railsguides.jp/security.html#ϦμΠϨΫτ ࣗ༝ʹϦμΠϨΫτͰ͖ͯ͠·͏

Slide 9

Slide 9 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ def url?(url) !url.match(/^https?:\/\/[^\n]+$/i).nil? end https://railsguides.jp/security.html#ਖ਼نදݱ

Slide 10

Slide 10 text

©2018 Wantedly, Inc. ਖ਼نදݱ def url?(url) !url.match(/^https?:\/\/[^\n]+$/i).nil? end irb(main):004:0> url?("https://example.com") => true irb(main):005:0> url?(" irb(main):006:1" hogehoge irb(main):007:1" https://example.com irb(main):008:1" ") => true https://railsguides.jp/security.html#ਖ਼نදݱ

Slide 11

Slide 11 text

©2018 Wantedly, Inc. ਖ਼نදݱ def url?(url) !url.match(/\Ahttps?:\/\/[^\n]+\z/i).nil? end https://railsguides.jp/security.html#ਖ਼نදݱ ^, $͸৔߹ʹΑͬͯةݥ

Slide 12

Slide 12 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ class UsersController < ApplicationController def activate user = User.find_by(activation_code: params[:code]) user.activate end end https://railsguides.jp/security.html#Ϣʔβʔ؅ཧ

Slide 13

Slide 13 text

©2018 Wantedly, Inc. nil νΣοΫෆ଍ class UsersController < ApplicationController def activate user = User.find_by(activation_code: params[:code]) user.activate end end http://localhost:3000/users/activate?code=

Slide 14

Slide 14 text

©2018 Wantedly, Inc. nil νΣοΫෆ଍ http://localhost:3000/users/activate?code= class UsersController < ApplicationController def activate user = User.find_by(activation_code: params[:code]) user.activate end end SELECT * FROM users WHERE (users.activation_code IS NULL) LIMIT 1 https://railsguides.jp/security.html#Ϣʔβʔ؅ཧ

Slide 15

Slide 15 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ hoge.html.erb hoge.html.haml <%= user_name %> = user_name _.template(`\ <%= user_name %> `) hoge.js (_ = underscore.js)

Slide 16

Slide 16 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ hoge.html.erb hoge.html.haml <%= user_name %> = user_name _.template(`\ <%= user_name %> `) hoge.js (_ = underscore.js) Τεέʔϓͳ͠ʢ<%-͕ྑ͍ʣ

Slide 17

Slide 17 text

©2018 Wantedly, Inc. ͜ͷίʔυʹ͸໰୊͕͋Δʂ ja.yml hoge.html.haml hoge.js ja: foo_html: “͜Μʹͪ͸
%{user_name}“ = t(“foo_html", user_name: “alert(‘XSS’)”) I18n.t(“foo_html", {user_name: “alert(‘XSS')"})

Slide 18

Slide 18 text

©2018 Wantedly, Inc. XSS(i18n-js) ja.yml hoge.html.haml hoge.js ͜Μʹͪ͸
<script>alert(‘XSS')</script> ͜Μʹͪ͸
alert('XSS') ja: foo_html: “͜Μʹͪ͸
%{user_name}“

Slide 19

Slide 19 text

©2018 Wantedly, Inc. XSS(i18n-js) https://railsguides.jp/i18n.html#҆શͳhtmlม׵

Slide 20

Slide 20 text

©2018 Wantedly, Inc. XSS(i18n-js) https://github.com/fnando/i18n-js/issues/485

Slide 21

Slide 21 text

©2018 Wantedly, Inc. XSS(i18n-js) https://github.com/fnando/i18n-js/issues/485

Slide 22

Slide 22 text

©2018 Wantedly, Inc. •ࣗ෼͕΍Γ͔Ͷͳ͍෦෼͕ଟ͔ͬͨ •๨Ε͕ͪͳ͜ͱ͕͋ΔͷͰఆظతʹ
 ηΩϡϦςΟΨΠυΛಡΈ͍ͨ ·ͱΊ