]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Correctly check import target URL IP
authorChocobozzz <me@florianbigard.com>
Mon, 7 Feb 2022 10:21:25 +0000 (11:21 +0100)
committerChocobozzz <me@florianbigard.com>
Mon, 7 Feb 2022 10:21:25 +0000 (11:21 +0100)
client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
server/helpers/dns.ts [new file with mode: 0644]
server/middlewares/validators/videos/video-imports.ts
server/tests/api/check-params/video-imports.ts
server/tests/helpers/dns.ts [new file with mode: 0644]
server/tests/helpers/index.ts

index 4e77cac4750e0087606e6b86997386780fef798f..fb6f2601b3ea6f93b314cbe2859f7bb533901b80 100644 (file)
@@ -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'
 
diff --git a/server/helpers/dns.ts b/server/helpers/dns.ts
new file mode 100644 (file)
index 0000000..da8b666
--- /dev/null
@@ -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
+}
index a3a5cc5315e5414de3da9b4e3b3c0cf00d6514dd..9c6d213c429d47baf2206924d8cfd0ba2833166a 100644 (file)
@@ -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.'
+        })
       }
     }
 
index 156a612ee7ab1cd9d861c3990c3f2a4c7d9e1a6b..7893f5cc58009c710acfc5d5c01cf1580ec81056 100644 (file)
@@ -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) {
diff --git a/server/tests/helpers/dns.ts b/server/tests/helpers/dns.ts
new file mode 100644 (file)
index 0000000..309de54
--- /dev/null
@@ -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
+  })
+})
index 91d11e25db766c443853f551f496881824f39365..951208842cba52f3dbaec491084e68f91d84fa6f 100644 (file)
@@ -1,5 +1,6 @@
 import './image'
 import './core-utils'
+import './dns'
 import './comment-model'
 import './markdown'
 import './request'