summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authorDerek <skehmatics@gmail.com>2022-12-02 16:13:36 -0500
committerGitHub <noreply@github.com>2022-12-03 06:13:36 +0900
commit66513b9893feedd7bc35c049e4e74f78cfde089e (patch)
tree6a330c7c9e9c0ce1761ca2bc740ee8ff7b5a8be7 /packages/backend
parentfix: add missing , (diff)
downloadmisskey-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')
-rw-r--r--packages/backend/src/core/remote/activitypub/ApInboxService.ts2
-rw-r--r--packages/backend/src/core/remote/activitypub/ApResolverService.ts5
-rw-r--r--packages/backend/src/core/remote/activitypub/models/ApPersonService.ts8
-rw-r--r--packages/backend/src/core/remote/activitypub/models/ApQuestionService.ts4
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)}`);