Non authenticated request cannot use pg_ catalogs/functions
This commit is contained in:
parent
9cc7c94406
commit
21b8e6947c
5
NEWS.md
5
NEWS.md
@ -1,6 +1,9 @@
|
|||||||
1.15.0 - 2014-mm-dd
|
1.14.1 - 2014-mm-dd
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
|
||||||
|
* Constraint for pg_ queries if request is non authenticated
|
||||||
|
|
||||||
1.14.0 - 2014-08-07
|
1.14.0 - 2014-08-07
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -276,7 +276,7 @@ function handleQuery(req, res) {
|
|||||||
pass: global.settings.db_pubuser_pass
|
pass: global.settings.db_pubuser_pass
|
||||||
};
|
};
|
||||||
|
|
||||||
var authenticated;
|
var authenticated = false;
|
||||||
|
|
||||||
var formatter;
|
var formatter;
|
||||||
|
|
||||||
@ -325,6 +325,7 @@ function handleQuery(req, res) {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
if (_.isBoolean(isAuthenticated) && isAuthenticated) {
|
if (_.isBoolean(isAuthenticated) && isAuthenticated) {
|
||||||
|
authenticated = isAuthenticated;
|
||||||
dbopts.user = _.template(global.settings.db_user, {user_id: dbParams.dbuser});
|
dbopts.user = _.template(global.settings.db_user, {user_id: dbParams.dbuser});
|
||||||
if ( global.settings.hasOwnProperty('db_user_pass') ) {
|
if ( global.settings.hasOwnProperty('db_user_pass') ) {
|
||||||
dbopts.pass = _.template(global.settings.db_user_pass, {
|
dbopts.pass = _.template(global.settings.db_user_pass, {
|
||||||
@ -386,6 +387,18 @@ function handleQuery(req, res) {
|
|||||||
tableCache.set(sql_md5, tableCacheItem);
|
tableCache.set(sql_md5, tableCacheItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !authenticated && tableCacheItem ) {
|
||||||
|
var affected_tables = tableCacheItem.affected_tables;
|
||||||
|
for ( var i = 0; i < affected_tables.length; ++i ) {
|
||||||
|
var t = affected_tables[i];
|
||||||
|
if ( t.match(/\bpg_/) ) {
|
||||||
|
var e = new SyntaxError("system tables are forbidden");
|
||||||
|
e.http_status = 403;
|
||||||
|
throw(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var fClass = formats[format];
|
var fClass = formats[format];
|
||||||
formatter = new fClass();
|
formatter = new fClass();
|
||||||
req.formatter = formatter;
|
req.formatter = formatter;
|
||||||
|
2
npm-shrinkwrap.json
generated
2
npm-shrinkwrap.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cartodb_sql_api",
|
"name": "cartodb_sql_api",
|
||||||
"version": "1.15.0",
|
"version": "1.14.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"underscore": {
|
"underscore": {
|
||||||
"version": "1.3.3"
|
"version": "1.3.3"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"cartodb"
|
"cartodb"
|
||||||
],
|
],
|
||||||
"version": "1.15.0",
|
"version": "1.14.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/CartoDB/CartoDB-SQL-API.git"
|
"url": "git://github.com/CartoDB/CartoDB-SQL-API.git"
|
||||||
|
@ -955,84 +955,66 @@ test('GET /api/v1/sql ensure cross domain set on errors', function(done){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('cannot GET system tables', function(done){
|
var systemQueriesSuitesToTest = [
|
||||||
var req = { headers: {host: 'vizzuality.cartodb.com'},
|
{
|
||||||
method: 'GET' };
|
desc: 'pg_ queries work with api_key and fail otherwise',
|
||||||
var pre = '/api/v1/sql?';
|
queries: [
|
||||||
Step(
|
'SELECT * FROM pg_attribute',
|
||||||
function trySysTable1() {
|
'SELECT * FROM PG_attribute',
|
||||||
req.url = pre + querystring.stringify({q: 'SELECT * FROM pg_attribute'});
|
'SELECT * FROM "pg_attribute"',
|
||||||
var next = this;
|
'SELECT a.* FROM untitle_table_4 a,pg_attribute'
|
||||||
assert.response( app, req, function(res) { next(null, res); } );
|
],
|
||||||
},
|
api_key_works: true,
|
||||||
function chkSysTable1_trySysTable2(err, res) {
|
no_api_key_works: false
|
||||||
if ( err ) throw err;
|
},
|
||||||
var next = this;
|
{
|
||||||
assert.equal(res.statusCode, 200);
|
desc: 'Possible false positive queries will work with api_key and without it',
|
||||||
req.url = pre + querystring.stringify({q: 'SELECT * FROM PG_attribute'});
|
queries: [
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
"SELECT 'pg_'",
|
||||||
},
|
'SELECT pg_attribute FROM ( select 1 as pg_attribute ) as f',
|
||||||
function chkSysTable2_trySysTable3(err, res) {
|
'SELECT * FROM cpg_test'
|
||||||
if ( err ) throw err;
|
],
|
||||||
var next = this;
|
api_key_works: true,
|
||||||
assert.equal(res.statusCode, 200);
|
no_api_key_works: true
|
||||||
req.url = pre + querystring.stringify({q: 'SELECT * FROM "pg_attribute"'});
|
},
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
{
|
||||||
},
|
desc: 'Set queries will FAIL for both api_key and no_api_key queries',
|
||||||
function chkSysTable3_trySysTable4(err, res) {
|
queries: [
|
||||||
if ( err ) throw err;
|
' SET work_mem TO 80000',
|
||||||
var next = this;
|
' set statement_timeout TO 400'
|
||||||
assert.equal(res.statusCode, 200);
|
],
|
||||||
req.url = pre + querystring.stringify({q: 'SELECT a.* FROM untitle_table_4 a,pg_attribute'});
|
api_key_works: false,
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
no_api_key_works: false
|
||||||
},
|
}
|
||||||
function chkSysTable4_tryValidPg1(err, res) {
|
];
|
||||||
if ( err ) throw err;
|
|
||||||
var next = this;
|
systemQueriesSuitesToTest.forEach(function(suiteToTest) {
|
||||||
assert.equal(res.statusCode, 200);
|
var apiKeyStatusErrorCode = !!suiteToTest.api_key_works ? 200 : 403;
|
||||||
req.url = pre + querystring.stringify({q: "SELECT 'pg_'"});
|
testSystemQueries(suiteToTest.desc + ' with api_key', suiteToTest.queries, apiKeyStatusErrorCode, '1234');
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
var noApiKeyStatusErrorCode = !!suiteToTest.no_api_key_works ? 200 : 403;
|
||||||
},
|
testSystemQueries(suiteToTest.desc, suiteToTest.queries, noApiKeyStatusErrorCode);
|
||||||
function chkValidPg1_tryValidPg2(err, res) {
|
});
|
||||||
if ( err ) throw err;
|
|
||||||
var next = this;
|
|
||||||
assert.equal(res.statusCode, 200);
|
function testSystemQueries(description, queries, statusErrorCode, apiKey) {
|
||||||
req.url = pre + querystring.stringify({q: "SELECT pg_attribute FROM ( select 1 as pg_attribute ) as f"});
|
queries.forEach(function(query) {
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
test('[' + description + '] query: ' + query, function(done) {
|
||||||
},
|
var queryStringParams = {q: query};
|
||||||
// See http://github.com/CartoDB/CartoDB-SQL-API/issues/118
|
if (!!apiKey) {
|
||||||
function chkValidPg1_tryValidPg3_b(err, res) {
|
queryStringParams.api_key = apiKey;
|
||||||
if ( err ) throw err;
|
}
|
||||||
var next = this;
|
var request = {
|
||||||
assert.equal(res.statusCode, 200, res.statusCode + ':' + res.body);
|
headers: {host: 'vizzuality.cartodb.com'},
|
||||||
req.url = pre + querystring.stringify({q: "SELECT * FROM cpg_test"});
|
method: 'GET',
|
||||||
assert.response(app, req, function(res) { next(null, res); });
|
url: '/api/v1/sql?' + querystring.stringify(queryStringParams)
|
||||||
},
|
};
|
||||||
function chkValidPg2_trySet1(err, res) {
|
assert.response(app, request, function(response) {
|
||||||
if ( err ) throw err;
|
assert.equal(response.statusCode, statusErrorCode);
|
||||||
var next = this;
|
done();
|
||||||
assert.equal(res.statusCode, 200, res.statusCode + ':' + res.body);
|
});
|
||||||
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);
|
|
||||||
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);
|
|
||||||
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){
|
||||||
assert.response(app, {
|
assert.response(app, {
|
||||||
|
Loading…
Reference in New Issue
Block a user