diff options
| author | Derek <skehmatics@gmail.com> | 2022-12-02 16:13:36 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-03 06:13:36 +0900 |
| commit | 66513b9893feedd7bc35c049e4e74f78cfde089e (patch) | |
| tree | 6a330c7c9e9c0ce1761ca2bc740ee8ff7b5a8be7 /packages/backend | |
| parent | fix: add missing , (diff) | |
| download | misskey-66513b9893feedd7bc35c049e4e74f78cfde089e.tar.gz misskey-66513b9893feedd7bc35c049e4e74f78cfde089e.tar.bz2 misskey-66513b9893feedd7bc35c049e4e74f78cfde089e.zip | |
fix(server): "forkbomb" DOS mitigation (#9247)
* Add recursion limit to resolver
* Use shared resolver in featured and question
* Changelog
* Changelog fix
* Update CHANGELOG.md
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
* Add host to recursion limit error message
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Diffstat (limited to 'packages/backend')
4 files changed, 12 insertions, 7 deletions
diff --git a/packages/backend/src/core/remote/activitypub/ApInboxService.ts b/packages/backend/src/core/remote/activitypub/ApInboxService.ts index baeeb1ad3e..3da384ec2d 100644 --- a/packages/backend/src/core/remote/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/remote/activitypub/ApInboxService.ts @@ -731,7 +731,7 @@ export class ApInboxService { await this.apPersonService.updatePerson(actor.uri!, resolver, object); return 'ok: Person updated'; } else if (getApType(object) === 'Question') { - await this.apQuestionService.updateQuestion(object).catch(err => console.error(err)); + await this.apQuestionService.updateQuestion(object, resolver).catch(err => console.error(err)); return 'ok: Question updated'; } else { return `skip: Unknown type: ${getApType(object)}`; diff --git a/packages/backend/src/core/remote/activitypub/ApResolverService.ts b/packages/backend/src/core/remote/activitypub/ApResolverService.ts index fe57c82ccc..bcdb9383d1 100644 --- a/packages/backend/src/core/remote/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/remote/activitypub/ApResolverService.ts @@ -76,6 +76,7 @@ export class Resolver { private httpRequestService: HttpRequestService, private apRendererService: ApRendererService, private apDbResolverService: ApDbResolverService, + private recursionLimit = 100 ) { this.history = new Set(); } @@ -116,6 +117,10 @@ export class Resolver { throw new Error('cannot resolve already resolved one'); } + if (this.history.size > this.recursionLimit) { + throw new Error(`hit recursion limit: ${this.utilityService.extractDbHost(value)}`); + } + this.history.add(value); const host = this.utilityService.extractDbHost(value); diff --git a/packages/backend/src/core/remote/activitypub/models/ApPersonService.ts b/packages/backend/src/core/remote/activitypub/models/ApPersonService.ts index 5135473862..f9d6f42ef6 100644 --- a/packages/backend/src/core/remote/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/remote/activitypub/models/ApPersonService.ts @@ -390,7 +390,7 @@ export class ApPersonService implements OnModuleInit { }); //#endregion - await this.updateFeatured(user!.id).catch(err => this.logger.error(err)); + await this.updateFeatured(user!.id, resolver).catch(err => this.logger.error(err)); return user!; } @@ -503,7 +503,7 @@ export class ApPersonService implements OnModuleInit { followerSharedInbox: person.sharedInbox ?? (person.endpoints ? person.endpoints.sharedInbox : undefined), }); - await this.updateFeatured(exist.id).catch(err => this.logger.error(err)); + await this.updateFeatured(exist.id, resolver).catch(err => this.logger.error(err)); } /** @@ -551,14 +551,14 @@ export class ApPersonService implements OnModuleInit { return { fields, services }; } - public async updateFeatured(userId: User['id']) { + public async updateFeatured(userId: User['id'], resolver?: Resolver) { const user = await this.usersRepository.findOneByOrFail({ id: userId }); if (!this.userEntityService.isRemoteUser(user)) return; if (!user.featured) return; this.logger.info(`Updating the featured: ${user.uri}`); - const resolver = this.apResolverService.createResolver(); + if (resolver == null) resolver = this.apResolverService.createResolver(); // Resolve to (Ordered)Collection Object const collection = await resolver.resolveCollection(user.featured); diff --git a/packages/backend/src/core/remote/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/remote/activitypub/models/ApQuestionService.ts index acd5cdae83..5793b98353 100644 --- a/packages/backend/src/core/remote/activitypub/models/ApQuestionService.ts +++ b/packages/backend/src/core/remote/activitypub/models/ApQuestionService.ts @@ -65,7 +65,7 @@ export class ApQuestionService { * @param uri URI of AP Question object * @returns true if updated */ - public async updateQuestion(value: any) { + public async updateQuestion(value: any, resolver?: Resolver) { const uri = typeof value === 'string' ? value : value.id; // URIがこのサーバーを指しているならスキップ @@ -80,7 +80,7 @@ export class ApQuestionService { //#endregion // resolve new Question object - const resolver = this.apResolverService.createResolver(); + if (resolver == null) resolver = this.apResolverService.createResolver(); const question = await resolver.resolve(value) as IQuestion; this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`); |