Skip to content

Commit

Permalink
Fix: HTTP signature validation
Browse files Browse the repository at this point in the history
Fix: HTTP signature validation

Fix: http signature

Fix: http signature

Fix: http signature

Fix: http signature
  • Loading branch information
atsu1125 committed Dec 27, 2023
1 parent 86fd53f commit a0c4766
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
"@koa/router": "9.0.1",
"@peertube/http-signature": "1.7.0",
"@sentry/browser": "7.5.1",
"@sentry/tracing": "5.29.2",
"@sinonjs/fake-timers": "10.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/queue/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Queue from 'bull';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';

import config from '../config';
import { ILocalUser } from '../models/entities/user';
Expand Down
7 changes: 6 additions & 1 deletion src/queue/processors/inbox.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Bull from 'bull';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';
import perform from '../../remote/activitypub/perform';
import Logger from '../../services/logger';
import { registerOrFetchInstanceDoc } from '../../services/register-or-fetch-instance-doc';
Expand All @@ -13,6 +13,7 @@ import { InboxJobData } from '..';
import DbResolver from '../../remote/activitypub/db-resolver';
import { resolvePerson } from '../../remote/activitypub/models/person';
import { LdSignature } from '../../remote/activitypub/misc/ld-signature';
import { verifySignature } from '../../remote/activitypub/check-fetch.js';

const logger = new Logger('inbox');

Expand Down Expand Up @@ -66,6 +67,10 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
// HTTP-Signatureの検証
const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem);

if (httpSignatureValidated) {
if (!verifySignature(signature, authUser.key)) return `skip: Invalid HTTP signature`;
}

// また、signatureのsignerは、activity.actorと一致する必要がある
if (!httpSignatureValidated || authUser.user.uri !== activity.actor) {
// 一致しなくても、でもLD-Signatureがありそうならそっちも見る
Expand Down
2 changes: 1 addition & 1 deletion src/queue/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DriveFile } from '../models/entities/drive-file';
import { User } from '../models/entities/user';
import { IActivity } from '../remote/activitypub/type';
import * as httpSignature from 'http-signature';
import * as httpSignature from '@peertube/http-signature';

export type DeliverJobData = {
/** Actor */
Expand Down
23 changes: 23 additions & 0 deletions src/remote/activitypub/check-fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IParsedSignature } from '@peertube/http-signature';
import { verify } from 'crypto';
import { createHash } from 'crypto';
import { toSingle } from '../../prelude/array';

export function verifySignature(sig: IParsedSignature, key: UserPublickey): boolean {
if (!['hs2019', 'rsa-sha256'].includes(sig.algorithm.toLowerCase())) return false;
try {
return verify('rsa-sha256', Buffer.from(sig.signingString, 'utf8'), key.keyPem, Buffer.from(sig.params.signature, 'base64'));
}
catch {
// Algo not supported
return false;
}
}

export function verifyDigest(body: string, digest: string | string[] | undefined): boolean {
digest = toSingle(digest);
if (body == null || digest == null || !digest.toLowerCase().startsWith('sha-256='))
return false;

return createHash('sha256').update(body).digest('base64') === digest.substring(8);
}
36 changes: 32 additions & 4 deletions src/server/activitypub.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as Router from '@koa/router';
import * as json from 'koa-json-body';
import * as httpSignature from 'http-signature';
import * as bodyParser from 'koa-bodyparser';
import * as httpSignature from '@peertube/http-signature';

import { renderActivity } from '../remote/activitypub/renderer';
import renderNote from '../remote/activitypub/renderer/note';
Expand All @@ -19,6 +20,8 @@ import { In } from 'typeorm';
import { ensure } from '../prelude/ensure';
import { renderLike } from '../remote/activitypub/renderer/like';
import config from '../config';
import { verifyDigest } from '../remote/activitypub/check-fetch.js';
import * as Koa from 'koa';

// Init router
const router = new Router();
Expand All @@ -28,15 +31,25 @@ const router = new Router();
function inbox(ctx: Router.RouterContext) {
if (config.disableFederation) ctx.throw(404);

if (ctx.req.headers.host !== config.host) {
ctx.status = 400;
return;
}

let signature;

try {
signature = httpSignature.parseRequest(ctx.req, { 'headers': [] });
signature = httpSignature.parseRequest(ctx.req, { headers: ['(request-target)', 'digest', 'host', 'date'] });
} catch (e) {
ctx.status = 401;
return;
}

if (!verifyDigest(ctx.request.rawBody, ctx.headers.digest)) {
ctx.status = 401;
return;
}

processInbox(ctx.request.body, signature);

ctx.status = 202;
Expand All @@ -60,9 +73,24 @@ export function setResponseType(ctx: Router.RouterContext) {
}
}

async function parseJsonBodyOrFail(ctx: Router.RouterContext, next: Koa.Next) {
const koaBodyParser = bodyParser({
enableTypes: ["json"],
detectJSON: () => true,
});

try {
await koaBodyParser(ctx, next);
}
catch {
ctx.status = 400;
return;
}
}

// inbox
router.post('/inbox', json(), inbox);
router.post('/users/:user/inbox', json(), inbox);
router.post('/inbox', parseJsonBodyOrFail, inbox);
router.post('/users/:user/inbox', parseJsonBodyOrFail, inbox);

// note
router.get('/notes/:note', async (ctx, next) => {
Expand Down
19 changes: 19 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,15 @@
dependencies:
mkdirp "^1.0.4"

"@peertube/http-signature@1.7.0":
version "1.7.0"
resolved "https://registry.yarnpkg.com/@peertube/http-signature/-/http-signature-1.7.0.tgz#12a84f3fc62e786aa3a2eb09426417bad65736dc"
integrity sha512-aGQIwo6/sWtyyqhVK4e1MtxYz4N1X8CNt6SOtCc+Wnczs5S5ONaLHDDR8LYaGn0MgOwvGgXyuZ5sJIfd7iyoUw==
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.14.1"

"@sentry/browser@7.5.1":
version "7.5.1"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.5.1.tgz#ba7a88b33ee8ed04d5425393a59e28dccb5f8f08"
Expand Down Expand Up @@ -6038,6 +6047,16 @@ jsonld@5.2.0:
lru-cache "^6.0.0"
rdf-canonize "^3.0.0"

jsprim@^1.2.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.4.0"
verror "1.10.0"

jsprim@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
Expand Down

0 comments on commit a0c4766

Please sign in to comment.