SQL Injection-safe call of polymorphic function

孤街醉人 提交于 2019-12-11 10:36:54

问题


Several times I've found myself refactoring web application code and end up wanting to do something like this (Groovy in this case, but could be anything):

Map getData(String relationName, Integer rowId) {
    def sql = Sql.newInstance([...])
    def result = sql.firstRow('SELECT getRelationRow(?,?)', relationName, rowId)
    sql.close()
    return new HashMap(result)
}

where the stored procedure getRelationRow(relname text, rowid integer) executes dynamic sql to retrieve the row of the specified rowid in the requested relation. The best example I've seen of such a function is this polymorphic function using anyelement type, and is called as

SELECT * FROM data_of(NULL::pcdmet, 17);

However to call this in the above code would require

def result = sql.firstRow("SELECT * FROM data_of(NULL::${relationName},?)",  rowId)

that is, it required the relation name to be pasted into the query, which risks SQL Injection. So is there away to keep the polymorphic goodness of the stored procedure but allow it to be called with generic relation names?


回答1:


I don't think it can be done this way. I assume Groovy is using prepared statements here, which requires that input and return types are known at prepare time, while my function derives the return type from the polymorphic input type.

I am pretty sure you need string concatenation. But don't fret, there are functions like pg_escape() to sanitize table names and make SQLi impossible. Don't know Groovy, but it should have that, too.

Or does it?

Based on the function data_of(..) at the end of this related answer:

  • Refactor a PL/pgSQL function to return the output of various SELECT queries

With PREPARE I can make this work by declaring the return type explicitly:

PREPARE fooplan ("relationName") AS  -- table name works as row type
SELECT * FROM data_of($1, $2);

Then I can hand in NULL, which is cast to "relationName" from the prepared context:

EXECUTE fooplan(NULL, 1);

So this might work after all, if your interface supports this. But you still have to concatenate the table name as return data type (and therefore defend against SQLi). Catch 22 I guess.



来源:https://stackoverflow.com/questions/28575899/sql-injection-safe-call-of-polymorphic-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!