Compare commits

...

2 commits

Author SHA1 Message Date
KMY(雪あすか)
d1e6027cf6
Bump version to 16.0 (#928) 2024-12-04 08:16:00 +09:00
KMY(雪あすか)
7348de7e41
Fix: フレンドサーバー申請時、ドメインを偽装して無関係のInboxを指定できる脆弱性 (#934) 2024-12-04 08:15:18 +09:00
6 changed files with 25 additions and 24 deletions

View file

@ -60,19 +60,13 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
already_accepted = friend.accepted? already_accepted = friend.accepted?
friend.update!(passive_state: :pending, active_state: :idle, passive_follow_activity_id: @json['id']) friend.update!(passive_state: :pending, active_state: :idle, passive_follow_activity_id: @json['id'])
else else
@friend = FriendDomain.new(domain: @account.domain, passive_state: :pending, passive_follow_activity_id: @json['id']) @friend = FriendDomain.create!(domain: @account.domain, passive_state: :pending, passive_follow_activity_id: @json['id'], inbox_url: @account.preferred_inbox_url)
@friend.inbox_url = @json['inboxUrl'].presence || @friend.default_inbox_url
@friend.save!
end end
if already_accepted || Setting.unlocked_friend friend.accept! if already_accepted || Setting.unlocked_friend
friend.accept!
# Notify for admin even if unlocked # Notify for admin
notify_staff_about_pending_friend_server! unless already_accepted notify_staff_about_pending_friend_server! unless already_accepted
else
notify_staff_about_pending_friend_server!
end
end end
def friend def friend

View file

@ -116,6 +116,7 @@ class FriendDomain < ApplicationRecord
object: ActivityPub::TagManager::COLLECTIONS[:public], object: ActivityPub::TagManager::COLLECTIONS[:public],
# Cannot use inbox_url method because this model also has inbox_url column # Cannot use inbox_url method because this model also has inbox_url column
# This is deprecated property. Newer version's kmyblue will ignore it.
inboxUrl: "https://#{Rails.configuration.x.web_domain}/inbox", inboxUrl: "https://#{Rails.configuration.x.web_domain}/inbox",
} }
end end

View file

@ -59,7 +59,7 @@ services:
web: web:
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
build: . build: .
image: kmyblue:16.0-dev image: kmyblue:16.0
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bundle exec puma -C config/puma.rb command: bundle exec puma -C config/puma.rb
@ -83,7 +83,7 @@ services:
build: build:
dockerfile: ./streaming/Dockerfile dockerfile: ./streaming/Dockerfile
context: . context: .
image: kmyblue-streaming:16.0-dev image: kmyblue-streaming:16.0
restart: always restart: always
env_file: .env.production env_file: .env.production
command: node ./streaming/index.js command: node ./streaming/index.js
@ -101,7 +101,7 @@ services:
sidekiq: sidekiq:
build: . build: .
image: kmyblue:16.0-dev image: kmyblue:16.0
restart: always restart: always
env_file: .env.production env_file: .env.production
command: bundle exec sidekiq command: bundle exec sidekiq

View file

@ -18,8 +18,8 @@ module Mastodon
def kmyblue_flag def kmyblue_flag
# 'LTS' # 'LTS'
'dev' # 'dev'
# nil nil
end end
def major def major

View file

@ -380,11 +380,10 @@ RSpec.describe ActivityPub::Activity::Follow do
context 'when given a friend server' do context 'when given a friend server' do
subject { described_class.new(json, sender) } subject { described_class.new(json, sender) }
let(:sender) { Fabricate(:account, domain: 'abc.com', url: 'https://abc.com/#actor') } let(:sender) { Fabricate(:account, domain: 'abc.com', url: 'https://abc.com/#actor', shared_inbox_url: 'https://abc.com/shared_inbox') }
let!(:friend) { Fabricate(:friend_domain, domain: 'abc.com', inbox_url: 'https://example.com/inbox', passive_state: :idle) } let!(:friend) { Fabricate(:friend_domain, domain: 'abc.com', inbox_url: 'https://example.com/inbox', passive_state: :idle) }
let!(:owner_user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) } let!(:owner_user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) }
let!(:patch_user) { Fabricate(:user, role: Fabricate(:user_role, name: 'OhagiOps', permissions: UserRole::FLAGS[:manage_federation])) } let!(:patch_user) { Fabricate(:user, role: Fabricate(:user_role, name: 'OhagiOps', permissions: UserRole::FLAGS[:manage_federation])) }
let(:inbox_url) { nil }
let(:json) do let(:json) do
{ {
@ -393,7 +392,6 @@ RSpec.describe ActivityPub::Activity::Follow do
type: 'Follow', type: 'Follow',
actor: ActivityPub::TagManager.instance.uri_for(sender), actor: ActivityPub::TagManager.instance.uri_for(sender),
object: 'https://www.w3.org/ns/activitystreams#Public', object: 'https://www.w3.org/ns/activitystreams#Public',
inboxUrl: inbox_url,
}.with_indifferent_access }.with_indifferent_access
end end
@ -415,25 +413,34 @@ RSpec.describe ActivityPub::Activity::Follow do
expect(friend).to_not be_nil expect(friend).to_not be_nil
expect(friend.they_are_pending?).to be true expect(friend.they_are_pending?).to be true
expect(friend.passive_follow_activity_id).to eq 'foo' expect(friend.passive_follow_activity_id).to eq 'foo'
expect(friend.inbox_url).to eq 'https://abc.com/inbox' expect(friend.inbox_url).to eq 'https://abc.com/shared_inbox'
end end
end end
context 'when no record and inbox_url is specified' do context 'when old spec which no record and inbox_url is specified' do
let(:inbox_url) { 'https://ohagi.com/inbox' } let(:json) do
{
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'foo',
type: 'Follow',
actor: ActivityPub::TagManager.instance.uri_for(sender),
object: 'https://www.w3.org/ns/activitystreams#Public',
inboxUrl: 'https://evil.org/bad_inbox',
}.with_indifferent_access
end
before do before do
friend.destroy! friend.destroy!
end end
it 'marks the friend as pending' do it 'marks the friend as pending but inboxUrl is not working' do
subject.perform subject.perform
friend = FriendDomain.find_by(domain: 'abc.com') friend = FriendDomain.find_by(domain: 'abc.com')
expect(friend).to_not be_nil expect(friend).to_not be_nil
expect(friend.they_are_pending?).to be true expect(friend.they_are_pending?).to be true
expect(friend.passive_follow_activity_id).to eq 'foo' expect(friend.passive_follow_activity_id).to eq 'foo'
expect(friend.inbox_url).to eq 'https://ohagi.com/inbox' expect(friend.inbox_url).to eq 'https://abc.com/shared_inbox'
end end
end end

View file

@ -21,7 +21,6 @@ RSpec.describe FriendDomain do
type: 'Follow', type: 'Follow',
actor: 'https://cb6e6126.ngrok.io/actor', actor: 'https://cb6e6126.ngrok.io/actor',
object: 'https://www.w3.org/ns/activitystreams#Public', object: 'https://www.w3.org/ns/activitystreams#Public',
inboxUrl: 'https://cb6e6126.ngrok.io/inbox',
}))).to have_been_made.once }))).to have_been_made.once
end end
end end