1
0
Fork 0

Force signed headers in http signatures

Thanks Roger
This commit is contained in:
Chocobozzz 2020-11-12 10:42:25 +01:00
parent 2a9562fc58
commit 797d05bdd9
No known key found for this signature in database
GPG key ID: 583A612D890159BE
4 changed files with 39 additions and 3 deletions

View file

@ -50,7 +50,11 @@ function isHTTPSignatureVerified (httpSignatureParsed: any, actor: MActor): bool
}
function parseHTTPSignature (req: Request, clockSkew?: number) {
return httpSignature.parse(req, { clockSkew })
const headers = req.method === 'POST'
? HTTP_SIGNATURE.REQUIRED_HEADERS.POST
: HTTP_SIGNATURE.REQUIRED_HEADERS.ALL
return httpSignature.parse(req, { clockSkew, headers })
}
// JSONLD

View file

@ -513,6 +513,10 @@ const HTTP_SIGNATURE = {
HEADER_NAME: 'signature',
ALGORITHM: 'rsa-sha256',
HEADERS_TO_SIGN: [ '(request-target)', 'host', 'date', 'digest' ],
REQUIRED_HEADERS: {
ALL: [ '(request-target)', 'host', 'date' ],
POST: [ '(request-target)', 'host', 'date', 'digest' ]
},
CLOCK_SKEW_SECONDS: 1800
}

View file

@ -63,7 +63,16 @@ async function checkHttpSignature (req: Request, res: Response) {
const sig = req.headers[HTTP_SIGNATURE.HEADER_NAME] as string
if (sig && sig.startsWith('Signature ') === true) req.headers[HTTP_SIGNATURE.HEADER_NAME] = sig.replace(/^Signature /, '')
const parsed = parseHTTPSignature(req, HTTP_SIGNATURE.CLOCK_SKEW_SECONDS)
let parsed: any
try {
parsed = parseHTTPSignature(req, HTTP_SIGNATURE.CLOCK_SKEW_SECONDS)
} catch (err) {
logger.warn('Invalid signature because of exception in signature parser', { reqBody: req.body, err })
res.status(403).json({ error: err.message })
return false
}
const keyId = parsed.keyId
if (!keyId) {

View file

@ -99,13 +99,32 @@ describe('Test ActivityPub security', function () {
expect(response.statusCode).to.equal(403)
})
it('Should succeed with a valid HTTP signature', async function () {
it('Should reject requests without appropriate signed headers', async function () {
await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey)
await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
const headers = buildGlobalHeaders(body)
const signatureOptions = baseHttpSignature()
const badHeadersMatrix = [
[ '(request-target)', 'date', 'digest' ],
[ 'host', 'date', 'digest' ],
[ '(request-target)', 'host', 'digest' ]
]
for (const badHeaders of badHeadersMatrix) {
signatureOptions.headers = badHeaders
const { response } = await makePOSTAPRequest(url, body, signatureOptions, headers)
expect(response.statusCode).to.equal(403)
}
})
it('Should succeed with a valid HTTP signature', async function () {
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
const headers = buildGlobalHeaders(body)
const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
expect(response.statusCode).to.equal(204)