Skip to content
This repository has been archived by the owner on Jan 27, 2020. It is now read-only.

Commit

Permalink
Merge pull request mastodon#1221 from pixiv/cherry_pick_2_5_1
Browse files Browse the repository at this point in the history
Improve signature verification safeguards (mastodon#8959)
  • Loading branch information
abcang authored Oct 12, 2018
2 parents 87cbe51 + 64c53f3 commit 228f63f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
12 changes: 9 additions & 3 deletions app/controllers/concerns/signature_verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ def signed_request_account
return
end

if request.headers['Date'].present? && !matches_time_window?
@signature_verification_failure_reason = 'Signed request date outside acceptable time window'
@signed_request_account = nil
return
end

raw_signature = request.headers['Signature']
signature_params = {}

Expand Down Expand Up @@ -76,7 +82,7 @@ def request_body
def build_signed_string(signed_headers)
signed_headers = 'date' if signed_headers.blank?

signed_headers.split(' ').map do |signed_header|
signed_headers.downcase.split(' ').map do |signed_header|
if signed_header == Request::REQUEST_TARGET
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
elsif signed_header == 'digest'
Expand All @@ -89,12 +95,12 @@ def build_signed_string(signed_headers)

def matches_time_window?
begin
time_sent = DateTime.httpdate(request.headers['Date'])
time_sent = Time.httpdate(request.headers['Date'])
rescue ArgumentError
return false
end

(Time.now.utc - time_sent).abs <= 30
(Time.now.utc - time_sent).abs <= 12.hours
end

def body_digest
Expand Down
16 changes: 10 additions & 6 deletions app/lib/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ def linkify(text)

private

def html_entities
@html_entities ||= HTMLEntities.new
end

def encode(html)
HTMLEntities.new.encode(html)
html_entities.encode(html)
end

def strip_urls(text)
Expand Down Expand Up @@ -150,7 +154,7 @@ def encode_custom_emojis(html, emojis)
emoji = emoji_map[shortcode]

if emoji
replacement = "<img draggable=\"false\" class=\"emojione\" alt=\":#{shortcode}:\" title=\":#{shortcode}:\" src=\"#{emoji}\" />"
replacement = "<img draggable=\"false\" class=\"emojione\" alt=\":#{encode(shortcode)}:\" title=\":#{encode(shortcode)}:\" src=\"#{encode(emoji)}\" />"
before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : ''
html = before_html + replacement + html[i + 1..-1]
i += replacement.size - (shortcode.size + 2) - 1
Expand Down Expand Up @@ -219,7 +223,7 @@ def link_to_mention(entity, linkable_accounts)
return link_to_account(acct) unless linkable_accounts

account = linkable_accounts.find { |item| TagManager.instance.same_acct?(item.acct, acct) }
account ? mention_html(account) : "@#{acct}"
account ? mention_html(account) : "@#{encode(acct)}"
end

def link_to_account(acct)
Expand All @@ -228,7 +232,7 @@ def link_to_account(acct)
domain = nil if TagManager.instance.local_domain?(domain)
account = EntityCache.instance.mention(username, domain)

account ? mention_html(account) : "@#{acct}"
account ? mention_html(account) : "@#{encode(acct)}"
end

def link_to_hashtag(entity)
Expand All @@ -246,10 +250,10 @@ def link_html(url)
end

def hashtag_html(tag)
"<a href=\"#{tag_url(tag.downcase)}\" class=\"mention hashtag\" rel=\"tag\">#<span>#{tag}</span></a>"
"<a href=\"#{encode(tag_url(tag.downcase))}\" class=\"mention hashtag\" rel=\"tag\">#<span>#{encode(tag)}</span></a>"
end

def mention_html(account)
"<span class=\"h-card\"><a href=\"#{TagManager.instance.url_for(account)}\" class=\"u-url mention\">@<span>#{account.username}</span></a></span>"
"<span class=\"h-card\"><a href=\"#{encode(TagManager.instance.url_for(account))}\" class=\"u-url mention\">@<span>#{encode(account.username)}</span></a></span>"
end
end
24 changes: 24 additions & 0 deletions spec/controllers/concerns/signature_verification_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,30 @@ def alternative_success
end
end

context 'with request older than a day' do
before do
get :success

fake_request = Request.new(:get, request.url)
fake_request.add_headers({ 'Date' => 2.days.ago.utc.httpdate })
fake_request.on_behalf_of(author)

request.headers.merge!(fake_request.headers)
end

describe '#signed_request?' do
it 'returns true' do
expect(controller.signed_request?).to be true
end
end

describe '#signed_request_account' do
it 'returns nil' do
expect(controller.signed_request_account).to be_nil
end
end
end

context 'with body' do
before do
post :success, body: 'Hello world'
Expand Down

0 comments on commit 228f63f

Please sign in to comment.