backend: some validation fixes??

This commit is contained in:
fly_mc 2024-11-19 02:16:35 +08:00
parent 20ece1c408
commit 472891a42f
5 changed files with 36 additions and 12 deletions

View file

@ -49,7 +49,7 @@ export class UtilityService {
@bindThis
public isMediaSilencedHost(silencedHosts: string[] | undefined, host: string | null): boolean {
if (!silencedHosts || host == null) return false;
return silencedHosts.some(x => host.toLowerCase() === x);
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
}
@bindThis
@ -96,7 +96,7 @@ export class UtilityService {
@bindThis
public extractDbHost(uri: string): string {
const url = new URL(uri);
return this.toPuny(url.hostname);
return this.toPuny(url.host);
}
@bindThis
@ -111,6 +111,12 @@ export class UtilityService {
}
@bindThis
public punyHost(url: string): string {
const urlObj = new URL(url);
const host = `${this.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
return host;
}
public isFederationAllowedHost(host: string): boolean {
if (this.meta.federation === 'none') return false;
if (this.meta.federation === 'specified' && !this.meta.federationHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`))) return false;

View file

@ -15,7 +15,9 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import type Logger from '@/logger.js';
import type { IObject } from './type.js';
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
import { assertActivityMatchesUrls } from '@/core/activitypub/misc/check-against-url.js';
type Request = {
url: string;
@ -252,6 +254,11 @@ export class ApRequestService {
validateContentTypeSetAsActivityPub(res);
return await res.json();
const finalUrl = res.url; // redirects may have been involved
const activity = await res.json() as IObject;
assertActivityMatchesUrls(activity, [url, finalUrl]);
return activity;
}
}

View file

@ -16,6 +16,7 @@ import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js';
import { fromTuple } from '@/misc/from-tuple.js';
import { isCollectionOrOrderedCollection } from './type.js';
import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js';
@ -67,7 +68,10 @@ export class Resolver {
}
@bindThis
public async resolve(value: string | IObject): Promise<IObject> {
public async resolve(value: string | IObject | [string | IObject]): Promise<IObject> {
// eslint-disable-next-line no-param-reassign
value = fromTuple(value);
if (typeof value !== 'string') {
return value;
}
@ -95,7 +99,7 @@ export class Resolver {
}
if (!this.utilityService.isFederationAllowedHost(host)) {
throw new Error('Instance is blocked');
throw new Bull.UnrecoverableError('Instance is blocked');
}
if (this.config.signToActivityPubGet && !this.user) {
@ -114,6 +118,14 @@ export class Resolver {
throw new Error('invalid response');
}
// HttpRequestService / ApRequestService have already checked that
// `object.id` or `object.url` matches the URL used to fetch the
// object after redirects; here we double-check that no redirects
// bounced between hosts
if (object.id && (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value))) {
throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
}
return object;
}

View file

@ -129,12 +129,6 @@ export class ApPersonService implements OnModuleInit {
this.logger = this.apLoggerService.logger;
}
private punyHost(url: string): string {
const urlObj = new URL(url);
const host = `${this.utilityService.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
return host;
}
/**
* Validate and convert to actor object
* @param x Fetched object

View file

@ -27,7 +27,7 @@ export const meta = {
kind: 'read:account',
limit: {
duration: ms('1hour'),
duration: ms('1minute'),
max: 30,
},
@ -118,6 +118,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
]));
if (local != null) return local;
const host = this.utilityService.extractDbHost(uri);
// local object, not found in db? fail
if (this.utilityService.isSelfHost(host)) return null;
// リモートから一旦オブジェクトフェッチ
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(uri) as any;