Skip to content

Commit d200573

Browse files
Ari1cPeterRao
authored andcommitted
Fix bucket ssrf (#666)
* FIX: 修复bucketname ssrf 问题 * FIX: 添加正则校验
1 parent 3e6dac3 commit d200573

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

lib/bucket.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22

33
const assert = require('assert');
4+
const utils = require('./common/utils/checkBucketname');
45

56
const proto = exports;
67

@@ -16,6 +17,16 @@ function toArray(obj) {
1617
return [obj];
1718
}
1819

20+
/**
21+
* check Bucket name
22+
*/
23+
24+
proto._checkBucketName = function _checkBucketName(name) {
25+
if (!utils._checkBucketName(name)) {
26+
throw new Error('The bucket must be conform to the specifications');
27+
}
28+
};
29+
1930
/**
2031
* Bucket opertaions
2132
*/
@@ -62,11 +73,11 @@ proto.listBuckets = async function listBuckets(query, options) {
6273
};
6374

6475
proto.useBucket = function useBucket(name) {
65-
this.options.bucket = name;
66-
return this;
76+
return this.setBucket(name);
6777
};
6878

6979
proto.setBucket = function useBucket(name) {
80+
this._checkBucketName(name);
7081
this.options.bucket = name;
7182
return this;
7283
};
@@ -76,6 +87,7 @@ proto.getBucket = function getBucket() {
7687
};
7788

7889
proto.getBucketLocation = async function getBucketLocation(name, options) {
90+
this._checkBucketName(name);
7991
name = name || this.getBucket();
8092
const params = this._bucketRequestParams('GET', name, 'location', options);
8193
params.successStatuses = [200];
@@ -88,6 +100,7 @@ proto.getBucketLocation = async function getBucketLocation(name, options) {
88100
};
89101

90102
proto.getBucketInfo = async function getBucketInfo(name, options) {
103+
this._checkBucketName(name);
91104
name = name || this.getBucket();
92105
const params = this._bucketRequestParams('GET', name, 'bucketInfo', options);
93106
params.successStatuses = [200];
@@ -100,6 +113,7 @@ proto.getBucketInfo = async function getBucketInfo(name, options) {
100113
};
101114

102115
proto.putBucket = async function putBucket(name, options) {
116+
this._checkBucketName(name);
103117
options = options || {};
104118
const params = this._bucketRequestParams('PUT', name, '', options);
105119

@@ -131,6 +145,7 @@ proto.putBucket = async function putBucket(name, options) {
131145
};
132146

133147
proto.deleteBucket = async function deleteBucket(name, options) {
148+
this._checkBucketName(name);
134149
const params = this._bucketRequestParams('DELETE', name, '', options);
135150
const result = await this.request(params);
136151
if (result.status === 200 || result.status === 204) {
@@ -144,6 +159,7 @@ proto.deleteBucket = async function deleteBucket(name, options) {
144159
// acl
145160

146161
proto.putBucketACL = async function putBucketACL(name, acl, options) {
162+
this._checkBucketName(name);
147163
const params = this._bucketRequestParams('PUT', name, 'acl', options);
148164
params.headers = {
149165
'x-oss-acl': acl
@@ -157,6 +173,7 @@ proto.putBucketACL = async function putBucketACL(name, acl, options) {
157173
};
158174

159175
proto.getBucketACL = async function getBucketACL(name, options) {
176+
this._checkBucketName(name);
160177
const params = this._bucketRequestParams('GET', name, 'acl', options);
161178
params.successStatuses = [200];
162179
params.xmlResponse = true;
@@ -174,6 +191,7 @@ proto.getBucketACL = async function getBucketACL(name, options) {
174191
// logging
175192

176193
proto.putBucketLogging = async function putBucketLogging(name, prefix, options) {
194+
this._checkBucketName(name);
177195
const params = this._bucketRequestParams('PUT', name, 'logging', options);
178196
let xml = `${'<?xml version="1.0" encoding="UTF-8"?>\n<BucketLoggingStatus>\n' +
179197
'<LoggingEnabled>\n<TargetBucket>'}${name}</TargetBucket>\n`;
@@ -191,6 +209,7 @@ proto.putBucketLogging = async function putBucketLogging(name, prefix, options)
191209
};
192210

193211
proto.getBucketLogging = async function getBucketLogging(name, options) {
212+
this._checkBucketName(name);
194213
const params = this._bucketRequestParams('GET', name, 'logging', options);
195214
params.successStatuses = [200];
196215
params.xmlResponse = true;
@@ -204,6 +223,7 @@ proto.getBucketLogging = async function getBucketLogging(name, options) {
204223
};
205224

206225
proto.deleteBucketLogging = async function deleteBucketLogging(name, options) {
226+
this._checkBucketName(name);
207227
const params = this._bucketRequestParams('DELETE', name, 'logging', options);
208228
params.successStatuses = [204, 200];
209229
const result = await this.request(params);
@@ -215,6 +235,7 @@ proto.deleteBucketLogging = async function deleteBucketLogging(name, options) {
215235
// website
216236

217237
proto.putBucketWebsite = async function putBucketWebsite(name, config, options) {
238+
this._checkBucketName(name);
218239
// config: index, [error]
219240
const params = this._bucketRequestParams('PUT', name, 'website', options);
220241
config = config || {};
@@ -235,6 +256,7 @@ proto.putBucketWebsite = async function putBucketWebsite(name, config, options)
235256
};
236257

237258
proto.getBucketWebsite = async function getBucketWebsite(name, options) {
259+
this._checkBucketName(name);
238260
const params = this._bucketRequestParams('GET', name, 'website', options);
239261
params.successStatuses = [200];
240262
params.xmlResponse = true;
@@ -247,6 +269,7 @@ proto.getBucketWebsite = async function getBucketWebsite(name, options) {
247269
};
248270

249271
proto.deleteBucketWebsite = async function deleteBucketWebsite(name, options) {
272+
this._checkBucketName(name);
250273
const params = this._bucketRequestParams('DELETE', name, 'website', options);
251274
params.successStatuses = [204];
252275
const result = await this.request(params);
@@ -258,6 +281,7 @@ proto.deleteBucketWebsite = async function deleteBucketWebsite(name, options) {
258281
// lifecycle
259282

260283
proto.putBucketLifecycle = async function putBucketLifecycle(name, rules, options) {
284+
this._checkBucketName(name);
261285
// rules: [rule, ...]
262286
// rule: [id], prefix, status, expiration, [days or date]
263287
// status: 'Enabled' or 'Disabled'
@@ -287,6 +311,7 @@ proto.putBucketLifecycle = async function putBucketLifecycle(name, rules, option
287311
};
288312

289313
proto.getBucketLifecycle = async function getBucketLifecycle(name, options) {
314+
this._checkBucketName(name);
290315
const params = this._bucketRequestParams('GET', name, 'lifecycle', options);
291316
params.successStatuses = [200];
292317
params.xmlResponse = true;
@@ -317,6 +342,7 @@ proto.getBucketLifecycle = async function getBucketLifecycle(name, options) {
317342
};
318343

319344
proto.deleteBucketLifecycle = async function deleteBucketLifecycle(name, options) {
345+
this._checkBucketName(name);
320346
const params = this._bucketRequestParams('DELETE', name, 'lifecycle', options);
321347
params.successStatuses = [204];
322348
const result = await this.request(params);
@@ -326,6 +352,7 @@ proto.deleteBucketLifecycle = async function deleteBucketLifecycle(name, options
326352
};
327353

328354
proto.putBucketCORS = async function putBucketCORS(name, rules, options) {
355+
this._checkBucketName(name);
329356
rules = rules || [];
330357
assert(rules.length, 'rules is required');
331358
rules.forEach((rule) => {
@@ -371,6 +398,7 @@ proto.putBucketCORS = async function putBucketCORS(name, rules, options) {
371398
};
372399

373400
proto.getBucketCORS = async function getBucketCORS(name, options) {
401+
this._checkBucketName(name);
374402
const params = this._bucketRequestParams('GET', name, 'cors', options);
375403
params.successStatuses = [200];
376404
params.xmlResponse = true;
@@ -394,6 +422,7 @@ proto.getBucketCORS = async function getBucketCORS(name, options) {
394422
};
395423

396424
proto.deleteBucketCORS = async function deleteBucketCORS(name, options) {
425+
this._checkBucketName(name);
397426
const params = this._bucketRequestParams('DELETE', name, 'cors', options);
398427
params.successStatuses = [204];
399428
const result = await this.request(params);
@@ -405,6 +434,7 @@ proto.deleteBucketCORS = async function deleteBucketCORS(name, options) {
405434
// referer
406435

407436
proto.putBucketReferer = async function putBucketReferer(name, allowEmpty, referers, options) {
437+
this._checkBucketName(name);
408438
const params = this._bucketRequestParams('PUT', name, 'referer', options);
409439
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<RefererConfiguration>\n';
410440
xml += ` <AllowEmptyReferer>${allowEmpty ? 'true' : 'false'}</AllowEmptyReferer>\n`;
@@ -428,6 +458,7 @@ proto.putBucketReferer = async function putBucketReferer(name, allowEmpty, refer
428458
};
429459

430460
proto.getBucketReferer = async function getBucketReferer(name, options) {
461+
this._checkBucketName(name);
431462
const params = this._bucketRequestParams('GET', name, 'referer', options);
432463
params.successStatuses = [200];
433464
params.xmlResponse = true;
@@ -446,6 +477,7 @@ proto.getBucketReferer = async function getBucketReferer(name, options) {
446477
};
447478

448479
proto.deleteBucketReferer = async function deleteBucketReferer(name, options) {
480+
this._checkBucketName(name);
449481
return await this.putBucketReferer(name, true, null, options);
450482
};
451483

lib/common/utils/checkBucketname.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* check Bucket name
3+
*/
4+
5+
exports._checkBucketName = function (name) {
6+
const bucketRegex = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
7+
const checkBucket = bucketRegex.test(name);
8+
return checkBucket;
9+
};

test/node/bucket.test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,27 @@ describe('test/bucket.test.js', () => {
4848
await utils.cleanBucket(store, bucket);
4949
});
5050

51+
describe('setBucket()', () => {
52+
it('should check bucket name', async () => {
53+
try {
54+
const name = 'ali-oss-test-bucket-/';
55+
await store.setBucket(name);
56+
throw new Error('should not run');
57+
} catch (err) {
58+
assert(err.message === 'The bucket must be conform to the specifications');
59+
}
60+
});
61+
});
62+
63+
describe('getBucket()', () => {
64+
it('should get bucket name', async () => {
65+
const name = 'ali-oss-test-bucket';
66+
await store.setBucket(name);
67+
const res = store.getBucket();
68+
assert.equal(res, name);
69+
});
70+
});
71+
5172
describe('putBucket()', () => {
5273
let name;
5374
let archvieBucket;

0 commit comments

Comments
 (0)