Skip to content

Commit

Permalink
Add server side private IP blocking for data source endpoints validation
Browse files Browse the repository at this point in the history
Signed-off-by: Kristen Tian <tyarong@amazon.com>
  • Loading branch information
kristenTian committed Apr 21, 2023
1 parent 86d42bc commit 912bb5f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
UsernamePasswordTypedContent,
} from '../../common/data_sources';
import { EncryptionContext, CryptographyServiceSetup } from '../cryptography_service';
import { isValidURL } from '../util';

/**
* Describes the Credential Saved Objects Client Wrapper class,
Expand Down Expand Up @@ -138,15 +139,6 @@ export class DataSourceSavedObjectsClientWrapper {
};
};

private isValidUrl(endpoint: string) {
try {
const url = new URL(endpoint);
return Boolean(url) && (url.protocol === 'http:' || url.protocol === 'https:');
} catch (e) {
return false;
}
}

private async validateAndEncryptAttributes<T = unknown>(attributes: T) {
this.validateAttributes(attributes);

Expand Down Expand Up @@ -254,8 +246,8 @@ export class DataSourceSavedObjectsClientWrapper {
);
}

if (!this.isValidUrl(endpoint)) {
throw SavedObjectsErrorHelpers.createBadRequestError('"endpoint" attribute is not valid');
if (!isValidURL(endpoint)) {
throw SavedObjectsErrorHelpers.createBadRequestError('"endpoint" attribute is not valid or allowed');
}

if (!auth) {
Expand Down
84 changes: 84 additions & 0 deletions src/plugins/data_source/server/util/endpoint_validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import dns from 'dns-sync';
import IPCIDR from 'ip-cidr';

const BLOCK_LIST = [
'127.0.0.0/8',
'::1/128',
'169.254.0.0/16',
'fe80::/10',
'10.0.0.0/8',
'172.16.0.0/12',
'192.168.0.0/16',
'fc00::/7',
'0.0.0.0/8',
'100.64.0.0/10',
'192.0.0.0/24',
'192.0.2.0/24',
'198.18.0.0/15',
'192.88.99.0/24',
'198.51.100.0/24',
'203.0.113.0/24',
'224.0.0.0/4',
'240.0.0.0/4',
'255.255.255.255/32',
'::/128',
'2001:db8::/32',
'ff00::/8',
];

export function isValidURL(endpoint: string) {
// Check the format of URL, URL has be in the format as
// scheme://server/path/resource otherwise an TypeError
// would be thrown.
let url;
try {
url = new URL(endpoint);
} catch (err) {
return false;
}

if (!(Boolean(url) && (url.protocol === 'http:' || url.protocol === 'https:'))) {
return false;
}

const ip = getIpAddress(url);
if (!ip) {
return false;
}

// IP CIDR check if a specific IP address fall in the
// range of an IP address block
for (const bl of BLOCK_LIST) {
const cidr = new IPCIDR(bl);
if (cidr.contains(ip)) {
return false;
}
}
return true;
}

/**
* Resolve hostname to IP address
* @param {object} urlObject
* @returns {string} configuredIP
* or null if it cannot be resolve
* According to RFC, all IPv6 IP address needs to be in []
* such as [::1].
* So if we detect a IPv6 address, we remove brackets.
*/
function getIpAddress(urlObject: URL) {
const hostname = urlObject.hostname;
const configuredIP = dns.resolve(hostname);
if (configuredIP) {
return configuredIP;
}
if (hostname.startsWith('[') && hostname.endsWith(']')) {
return hostname.substr(1).slice(0, -1);
}
return null;
}
6 changes: 6 additions & 0 deletions src/plugins/data_source/server/util/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { isValidURL } from './endpoint_validator';

0 comments on commit 912bb5f

Please sign in to comment.