Postgresql 将函数调用识别为前端和后端之间的代理

Postgresql 将函数调用识别为前端和后端之间的代理,postgresql,proxy,wireshark,packet-sniffers,function-call,Postgresql,Proxy,Wireshark,Packet Sniffers,Function Call,根据我发现的问题,我不能期望使用'F'标识符作为代理查找函数调用 我做了更多的研究,现在我认为postgreSQL用来发送参数化语句,比如函数。(如果我错了,请纠正我) 我知道执行也将使用扩展查询协议(我认为应该有更多使用此协议的语句) 所以我认为这不应该是将函数调用识别为代理的方法。还有别的办法吗?有可能吗?还是我完全迷失了方向,误解了一切 通过识别函数调用,我的意思是我需要识别函数调用,并作为前端后端连接(客户端和服务器之间)中的第三方调查传递的参数和函数名,但这些参数不一定与函数参数相同

根据我发现的问题,我不能期望使用
'F'
标识符作为代理查找函数调用

我做了更多的研究,现在我认为postgreSQL用来发送参数化语句,比如函数。(如果我错了,请纠正我)

我知道执行也将使用扩展查询协议(我认为应该有更多使用此协议的语句)

所以我认为这不应该是将函数调用识别为代理的方法。还有别的办法吗?有可能吗?还是我完全迷失了方向,误解了一切

通过识别函数调用,我的意思是我需要识别函数调用,并作为前端后端连接(客户端和服务器之间)中的第三方调查传递的参数和函数名,但这些参数不一定与函数参数相同

若要使用示例,请发送如下函数调用:

res = PQexec(conn, "SELECT myfun(42)");
const Oid types[1] = { INT4OID };
const char * const vals[1] = { "42" };

res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
SELECT val FROM mytab WHERE id = $1;
SELECT myfun((SELECT val FROM tab WHERE id = 42));
它将以带有
'Q'
(查询)标识符的数据包发送

如果您这样发送:

res = PQexec(conn, "SELECT myfun(42)");
const Oid types[1] = { INT4OID };
const char * const vals[1] = { "42" };

res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
SELECT val FROM mytab WHERE id = $1;
SELECT myfun((SELECT val FROM tab WHERE id = 42));
查询将在带有
'p'
(解析)标识符的数据包中发送,参数将在以下
'B'
(绑定)数据包中发送

但这与函数调用无关,对于这样的查询也会发生同样的情况:

res = PQexec(conn, "SELECT myfun(42)");
const Oid types[1] = { INT4OID };
const char * const vals[1] = { "42" };

res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
SELECT val FROM mytab WHERE id = $1;
SELECT myfun((SELECT val FROM tab WHERE id = 42));
您说您的目标是监听前端后端协议,过滤掉所有函数调用和传递给它们的参数

这是一项非常艰巨的任务;本质上,这意味着您必须解析发送到服务器的SQL语句,这意味着您必须至少复制PostgreSQL解析器的一部分。您必须记住一些已解析的语句,并从绑定数据包中注入参数

除此之外,我还想到两个问题:

  • 这样您就不能捕获函数内部发出的函数调用,这有关系吗

  • 在以下情况下,如何确定传递的参数:

    res = PQexec(conn, "SELECT myfun(42)");
    
    const Oid types[1] = { INT4OID };
    const char * const vals[1] = { "42" };
    
    res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
    
    SELECT val FROM mytab WHERE id = $1;
    
    SELECT myfun((SELECT val FROM tab WHERE id = 42));
    
    或者这个:

    SELECT myfun(CAST(otherfun(42) || '0' AS integer));
    
  • 也许有更好的方法来实现您想要的,比如黑客攻击PostgreSQL server,并在函数实际调用的位置提取信息。

    PostgreSQL使用扩展查询协议处理带参数的语句,但这些参数不一定与函数参数相同

    若要使用示例,请发送如下函数调用:

    res = PQexec(conn, "SELECT myfun(42)");
    
    const Oid types[1] = { INT4OID };
    const char * const vals[1] = { "42" };
    
    res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
    
    SELECT val FROM mytab WHERE id = $1;
    
    SELECT myfun((SELECT val FROM tab WHERE id = 42));
    
    它将以带有
    'Q'
    (查询)标识符的数据包发送

    如果您这样发送:

    res = PQexec(conn, "SELECT myfun(42)");
    
    const Oid types[1] = { INT4OID };
    const char * const vals[1] = { "42" };
    
    res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
    
    SELECT val FROM mytab WHERE id = $1;
    
    SELECT myfun((SELECT val FROM tab WHERE id = 42));
    
    查询将在带有
    'p'
    (解析)标识符的数据包中发送,参数将在以下
    'B'
    (绑定)数据包中发送

    但这与函数调用无关,对于这样的查询也会发生同样的情况:

    res = PQexec(conn, "SELECT myfun(42)");
    
    const Oid types[1] = { INT4OID };
    const char * const vals[1] = { "42" };
    
    res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
    
    SELECT val FROM mytab WHERE id = $1;
    
    SELECT myfun((SELECT val FROM tab WHERE id = 42));
    
    您说您的目标是监听前端后端协议,过滤掉所有函数调用和传递给它们的参数

    这是一项非常艰巨的任务;本质上,这意味着您必须解析发送到服务器的SQL语句,这意味着您必须至少复制PostgreSQL解析器的一部分。您必须记住一些已解析的语句,并从绑定数据包中注入参数

    除此之外,我还想到两个问题:

  • 这样您就不能捕获函数内部发出的函数调用,这有关系吗

  • 在以下情况下,如何确定传递的参数:

    res = PQexec(conn, "SELECT myfun(42)");
    
    const Oid types[1] = { INT4OID };
    const char * const vals[1] = { "42" };
    
    res = PQexecParams(conn, "SELECT myfun($1)", 1, types, vals, NULL, NULL, 0);
    
    SELECT val FROM mytab WHERE id = $1;
    
    SELECT myfun((SELECT val FROM tab WHERE id = 42));
    
    或者这个:

    SELECT myfun(CAST(otherfun(42) || '0' AS integer));
    

  • 也许有更好的方法来实现您的目标,比如入侵PostgreSQL server并在函数实际调用的位置提取您的信息。

    谢谢,您完全正确,您提到的这两个问题也是我的问题,但现在我只关注简单的调用。黑客服务器不是一个选项,因为它应该作为代理。另一个问题刚刚浮现在我的脑海中,因为postgreSQL使用扩展查询协议处理带有参数的语句,例如,如果我们有一个准备好的语句和一个具有相同名称和参数的函数,那个么服务器将如何为客户机调用选择正确的执行方法呢?仅使用
    select
    execute
    语句?没有歧义。您可以使用SQL函数或使用执行准备好的语句。在这两种情况下都不能出现函数名。谢谢,你完全正确,你提到的这两个问题也是我的问题,但现在我只关注简单的调用。黑客服务器不是一个选项,因为它应该作为代理。另一个问题刚刚浮现在我的脑海中,因为postgreSQL使用扩展查询协议处理带有参数的语句,例如,如果我们有一个准备好的语句和一个具有相同名称和参数的函数,那个么服务器将如何为客户机调用选择正确的执行方法呢?仅使用
    select
    execute
    语句?没有歧义。您可以使用SQL函数或使用执行准备好的语句。在这两种情况下,都不能存在函数名。