Make using SET or querying system catalogues harder
An hack to "prevent" querying system tables already existed but was pretty weak. This commits makes that a bit stronger. The filter for SET is new.
This commit is contained in:
parent
bc068a5463
commit
1bcffbc68c
1
NEWS.md
1
NEWS.md
@ -1,5 +1,6 @@
|
|||||||
1.3.8
|
1.3.8
|
||||||
-----
|
-----
|
||||||
|
* Make using SET or querying system catalogues harder
|
||||||
|
|
||||||
1.3.7
|
1.3.7
|
||||||
-----
|
-----
|
||||||
|
@ -99,15 +99,23 @@ var PSQL = function(user_id, db, limit, offset){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// throw exception if system table detected
|
// throw exception if illegal operations are detected
|
||||||
|
// NOTE: this check is weak hack, better database
|
||||||
|
// permissions should be used instead.
|
||||||
me.sanitize = function(sql, callback){
|
me.sanitize = function(sql, callback){
|
||||||
if (sql.match(/\s+pg_.+/)){
|
if (sql.match(/\s+"?pg_.+/i)){
|
||||||
var error = new SyntaxError("system tables are forbidden");
|
var error = new SyntaxError("system tables are forbidden");
|
||||||
error.http_status = 403;
|
error.http_status = 403;
|
||||||
throw error;
|
callback(error);
|
||||||
} else {
|
return;
|
||||||
callback(null,true);
|
|
||||||
}
|
}
|
||||||
|
if (sql.match(/^\s+set\s+/i)){
|
||||||
|
var error = new SyntaxError("SET command is forbidden");
|
||||||
|
error.http_status = 403;
|
||||||
|
callback(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(null,true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return me;
|
return me;
|
||||||
|
@ -22,6 +22,7 @@ var app = require(global.settings.app_root + '/app/controllers/app')
|
|||||||
, zipfile = require('zipfile')
|
, zipfile = require('zipfile')
|
||||||
, fs = require('fs')
|
, fs = require('fs')
|
||||||
, libxmljs = require('libxmljs')
|
, libxmljs = require('libxmljs')
|
||||||
|
, Step = require('step')
|
||||||
;
|
;
|
||||||
|
|
||||||
// allow lots of emitters to be set to silence warning
|
// allow lots of emitters to be set to silence warning
|
||||||
@ -621,18 +622,68 @@ test('GET /api/v1/sql ensure cross domain set on errors', function(done){
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('cannot GET system tables', function(done){
|
test('cannot GET system tables', function(done){
|
||||||
assert.response(app, {
|
var req = { headers: {host: 'vizzuality.cartodb.com'},
|
||||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20pg_attribute',
|
method: 'GET' };
|
||||||
headers: {host: 'vizzuality.cartodb.com'},
|
var pre = '/api/v1/sql?';
|
||||||
method: 'GET'
|
Step(
|
||||||
},{
|
function trySysTable1() {
|
||||||
status: 403
|
req.url = pre + querystring.stringify({q: 'SELECT * FROM pg_attribute'});
|
||||||
}, function(res) {
|
var next = this;
|
||||||
|
assert.response( app, req, function(res) { next(null, res); } );
|
||||||
|
},
|
||||||
|
function chkSysTable1_trySysTable2(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
var next = this;
|
||||||
|
assert.equal(res.statusCode, 403);
|
||||||
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||||
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
||||||
// TODO: check actual error message...
|
// TODO: check actual error message...
|
||||||
done();
|
req.url = pre + querystring.stringify({q: 'SELECT * FROM PG_attribute'});
|
||||||
});
|
assert.response(app, req, function(res) { next(null, res); });
|
||||||
|
},
|
||||||
|
function chkSysTable2_trySysTable3(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
var next = this;
|
||||||
|
assert.equal(res.statusCode, 403);
|
||||||
|
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||||
|
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
||||||
|
// TODO: check actual error message...
|
||||||
|
req.url = pre + querystring.stringify({q: 'SELECT * FROM "pg_attribute"'});
|
||||||
|
assert.response(app, req, function(res) { next(null, res); });
|
||||||
|
},
|
||||||
|
function chkSysTable3_trySet1(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
var next = this;
|
||||||
|
assert.equal(res.statusCode, 403);
|
||||||
|
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||||
|
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
||||||
|
// TODO: check actual error message...
|
||||||
|
req.url = pre + querystring.stringify({q: ' set statement_timeout TO 400'});
|
||||||
|
assert.response(app, req, function(res) { next(null, res); });
|
||||||
|
},
|
||||||
|
function chkSet1_trySet2(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
var next = this;
|
||||||
|
assert.equal(res.statusCode, 403);
|
||||||
|
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||||
|
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
||||||
|
// TODO: check actual error message...
|
||||||
|
req.url = pre + querystring.stringify({q: ' SET work_mem TO 80000'});
|
||||||
|
assert.response(app, req, function(res) { next(null, res); });
|
||||||
|
},
|
||||||
|
function chkSet2(err, res) {
|
||||||
|
if ( err ) throw err;
|
||||||
|
var next = this;
|
||||||
|
assert.equal(res.statusCode, 403);
|
||||||
|
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||||
|
assert.deepEqual(res.headers['content-disposition'], 'inline');
|
||||||
|
// TODO: check actual error message...
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
function finish(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('GET decent error if domain is incorrect', function(done){
|
test('GET decent error if domain is incorrect', function(done){
|
||||||
|
Loading…
Reference in New Issue
Block a user