mirror of https://github.com/Chocobozzz/PeerTube
Correctly check import target URL IP
parent
4afec73571
commit
f33e515991
|
@ -9,7 +9,7 @@ import { genericUploadErrorHandler, scrollToTop } from '@app/helpers'
|
|||
import { FormValidatorService } from '@app/shared/shared-forms'
|
||||
import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
|
||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||
import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
|
||||
import { HttpStatusCode, VideoCreateResult } from '@shared/models'
|
||||
import { UploaderXFormData } from './uploaderx-form-data'
|
||||
import { VideoSend } from './video-send'
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import { lookup } from 'dns'
|
||||
import { parse as parseIP } from 'ipaddr.js'
|
||||
|
||||
function dnsLookupAll (hostname: string) {
|
||||
return new Promise<string[]>((res, rej) => {
|
||||
lookup(hostname, { family: 0, all: true }, (err, adresses) => {
|
||||
if (err) return rej(err)
|
||||
|
||||
return res(adresses.map(a => a.address))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function isResolvingToUnicastOnly (hostname: string) {
|
||||
const addresses = await dnsLookupAll(hostname)
|
||||
|
||||
for (const address of addresses) {
|
||||
const parsed = parseIP(address)
|
||||
|
||||
if (parsed.range() !== 'unicast') return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export {
|
||||
dnsLookupAll,
|
||||
isResolvingToUnicastOnly
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import express from 'express'
|
||||
import { body, param } from 'express-validator'
|
||||
import { isValid as isIPValid, parse as parseIP } from 'ipaddr.js'
|
||||
import { isResolvingToUnicastOnly } from '@server/helpers/dns'
|
||||
import { isPreImportVideoAccepted } from '@server/lib/moderation'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { MUserAccountId, MVideoImport } from '@server/types/models'
|
||||
|
@ -76,17 +76,13 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([
|
|||
if (req.body.targetUrl) {
|
||||
const hostname = new URL(req.body.targetUrl).hostname
|
||||
|
||||
if (isIPValid(hostname)) {
|
||||
const parsed = parseIP(hostname)
|
||||
if (await isResolvingToUnicastOnly(hostname) !== true) {
|
||||
cleanUpReqFiles(req)
|
||||
|
||||
if (parsed.range() !== 'unicast') {
|
||||
cleanUpReqFiles(req)
|
||||
|
||||
return res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'Cannot use non unicast IP as targetUrl.'
|
||||
})
|
||||
}
|
||||
return res.fail({
|
||||
status: HttpStatusCode.FORBIDDEN_403,
|
||||
message: 'Cannot use non unicast IP as targetUrl.'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,8 @@ describe('Test video imports API validator', function () {
|
|||
'http://127.0.0.1',
|
||||
'http://127.0.0.1/hello',
|
||||
'https://192.168.1.42',
|
||||
'http://192.168.1.42'
|
||||
'http://192.168.1.42',
|
||||
'http://127.0.0.1.cpy.re'
|
||||
]
|
||||
|
||||
for (const targetUrl of targetUrls) {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import { isResolvingToUnicastOnly } from '@server/helpers/dns'
|
||||
|
||||
describe('DNS helpers', function () {
|
||||
|
||||
it('Should correctly check unicast IPs', async function () {
|
||||
expect(await isResolvingToUnicastOnly('cpy.re')).to.be.true
|
||||
expect(await isResolvingToUnicastOnly('framasoft.org')).to.be.true
|
||||
expect(await isResolvingToUnicastOnly('8.8.8.8')).to.be.true
|
||||
|
||||
expect(await isResolvingToUnicastOnly('127.0.0.1')).to.be.false
|
||||
expect(await isResolvingToUnicastOnly('127.0.0.1.cpy.re')).to.be.false
|
||||
})
|
||||
})
|
|
@ -1,5 +1,6 @@
|
|||
import './image'
|
||||
import './core-utils'
|
||||
import './dns'
|
||||
import './comment-model'
|
||||
import './markdown'
|
||||
import './request'
|
||||
|
|
Loading…
Reference in New Issue