aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-02-07 11:21:25 +0100
committerChocobozzz <me@florianbigard.com>2022-02-07 11:21:25 +0100
commitf33e515991a32885622b217bf2ed1d1b0d9d6832 (patch)
tree43bf9e63c821f2b363ee60e8b1de07ab7c883580 /server
parent4afec7357129590b0e0f3558ecb9ac20e0903600 (diff)
downloadPeerTube-f33e515991a32885622b217bf2ed1d1b0d9d6832.tar.gz
PeerTube-f33e515991a32885622b217bf2ed1d1b0d9d6832.tar.zst
PeerTube-f33e515991a32885622b217bf2ed1d1b0d9d6832.zip
Correctly check import target URL IP
Diffstat (limited to 'server')
-rw-r--r--server/helpers/dns.ts29
-rw-r--r--server/middlewares/validators/videos/video-imports.ts18
-rw-r--r--server/tests/api/check-params/video-imports.ts3
-rw-r--r--server/tests/helpers/dns.ts17
-rw-r--r--server/tests/helpers/index.ts1
5 files changed, 56 insertions, 12 deletions
diff --git a/server/helpers/dns.ts b/server/helpers/dns.ts
new file mode 100644
index 000000000..da8b666c2
--- /dev/null
+++ b/server/helpers/dns.ts
@@ -0,0 +1,29 @@
1import { lookup } from 'dns'
2import { parse as parseIP } from 'ipaddr.js'
3
4function dnsLookupAll (hostname: string) {
5 return new Promise<string[]>((res, rej) => {
6 lookup(hostname, { family: 0, all: true }, (err, adresses) => {
7 if (err) return rej(err)
8
9 return res(adresses.map(a => a.address))
10 })
11 })
12}
13
14async function isResolvingToUnicastOnly (hostname: string) {
15 const addresses = await dnsLookupAll(hostname)
16
17 for (const address of addresses) {
18 const parsed = parseIP(address)
19
20 if (parsed.range() !== 'unicast') return false
21 }
22
23 return true
24}
25
26export {
27 dnsLookupAll,
28 isResolvingToUnicastOnly
29}
diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts
index a3a5cc531..9c6d213c4 100644
--- a/server/middlewares/validators/videos/video-imports.ts
+++ b/server/middlewares/validators/videos/video-imports.ts
@@ -1,6 +1,6 @@
1import express from 'express' 1import express from 'express'
2import { body, param } from 'express-validator' 2import { body, param } from 'express-validator'
3import { isValid as isIPValid, parse as parseIP } from 'ipaddr.js' 3import { isResolvingToUnicastOnly } from '@server/helpers/dns'
4import { isPreImportVideoAccepted } from '@server/lib/moderation' 4import { isPreImportVideoAccepted } from '@server/lib/moderation'
5import { Hooks } from '@server/lib/plugins/hooks' 5import { Hooks } from '@server/lib/plugins/hooks'
6import { MUserAccountId, MVideoImport } from '@server/types/models' 6import { MUserAccountId, MVideoImport } from '@server/types/models'
@@ -76,17 +76,13 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([
76 if (req.body.targetUrl) { 76 if (req.body.targetUrl) {
77 const hostname = new URL(req.body.targetUrl).hostname 77 const hostname = new URL(req.body.targetUrl).hostname
78 78
79 if (isIPValid(hostname)) { 79 if (await isResolvingToUnicastOnly(hostname) !== true) {
80 const parsed = parseIP(hostname) 80 cleanUpReqFiles(req)
81 81
82 if (parsed.range() !== 'unicast') { 82 return res.fail({
83 cleanUpReqFiles(req) 83 status: HttpStatusCode.FORBIDDEN_403,
84 84 message: 'Cannot use non unicast IP as targetUrl.'
85 return res.fail({ 85 })
86 status: HttpStatusCode.FORBIDDEN_403,
87 message: 'Cannot use non unicast IP as targetUrl.'
88 })
89 }
90 } 86 }
91 } 87 }
92 88
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts
index 156a612ee..7893f5cc5 100644
--- a/server/tests/api/check-params/video-imports.ts
+++ b/server/tests/api/check-params/video-imports.ts
@@ -120,7 +120,8 @@ describe('Test video imports API validator', function () {
120 'http://127.0.0.1', 120 'http://127.0.0.1',
121 'http://127.0.0.1/hello', 121 'http://127.0.0.1/hello',
122 'https://192.168.1.42', 122 'https://192.168.1.42',
123 'http://192.168.1.42' 123 'http://192.168.1.42',
124 'http://127.0.0.1.cpy.re'
124 ] 125 ]
125 126
126 for (const targetUrl of targetUrls) { 127 for (const targetUrl of targetUrls) {
diff --git a/server/tests/helpers/dns.ts b/server/tests/helpers/dns.ts
new file mode 100644
index 000000000..309de5426
--- /dev/null
+++ b/server/tests/helpers/dns.ts
@@ -0,0 +1,17 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { expect } from 'chai'
5import { isResolvingToUnicastOnly } from '@server/helpers/dns'
6
7describe('DNS helpers', function () {
8
9 it('Should correctly check unicast IPs', async function () {
10 expect(await isResolvingToUnicastOnly('cpy.re')).to.be.true
11 expect(await isResolvingToUnicastOnly('framasoft.org')).to.be.true
12 expect(await isResolvingToUnicastOnly('8.8.8.8')).to.be.true
13
14 expect(await isResolvingToUnicastOnly('127.0.0.1')).to.be.false
15 expect(await isResolvingToUnicastOnly('127.0.0.1.cpy.re')).to.be.false
16 })
17})
diff --git a/server/tests/helpers/index.ts b/server/tests/helpers/index.ts
index 91d11e25d..951208842 100644
--- a/server/tests/helpers/index.ts
+++ b/server/tests/helpers/index.ts
@@ -1,5 +1,6 @@
1import './image' 1import './image'
2import './core-utils' 2import './core-utils'
3import './dns'
3import './comment-model' 4import './comment-model'
4import './markdown' 5import './markdown'
5import './request' 6import './request'