0

我一直在为 c# 使用带有 neo4j 客户端的WithParams,但 withParams 不适用于标签或关系类型。

我当时想到的替代方法是连接我想要基于某个标签作为参数形成的字符串,然后构造密码查询。那是:

string optionalMatchString = $"p =(n1)-[{relationshipsString}]-(n2)";
graphClient.Cypher.Match("(n1)")
           .Where((Node n1) => n1.Identifier == identifier)
           .OptionalMatch(optionalMatchString)

你可以猜到,relationshipString 是传递给我的一个参数。如果我使用 WithParams 查询将不会替换参数,所以现在我连接字符串,但这很容易受到攻击......(是吗?)

我了解了APOC并看到了这个问题

这是我看到的一个例子

CALL db.labels() yield label
call apoc.cypher.run("MATCH (n:`"+label+"`) RETURN keys(n) as keys LIMIT 1",{}) yield value as row
RETURN label, row.keys as keys

显然,有一个称为 APOC 的程序cypher.run,我可以在其中将我的标签(或相关的关系)作为变量(来自参数),但据我所见,它们只是连接一个字符串......所以是一样的我一直在做什么?或者 APOC 是否以某种方式在查询之上执行其他操作?APOC 程序对注射是否“安全”?

4

2 回答 2

1

如果您的数据库中有一组预定义的关系,您可以将关系类型列入白名单,即检查它是否是可能的关系类型的成员。

如果由于某种原因这对您不起作用,您仍然可以将标签作为参数传递并使用labelsCypher 中的方法。但是,这将不利于性能,因为数据库将查询所有节点并使用过滤操作检查它们的类型。

我知道这是一个 C# 问题,但让我分享一些 Java 代码来重现它:

GraphDatabaseService gds = new TestGraphDatabaseFactory()
    .newImpermanentDatabaseBuilder().newGraphDatabase();
ApocHelper.registerProcedure(gds, Cypher.class);
gds.execute("CREATE (:MyLabel {attr1: 'hello'})");
Result result = gds.execute(
    "CALL apoc.cypher.run(" +
        "'MATCH (n) WHERE $label1 IN labels(n) RETURN keys(n) as keys LIMIT 1', " +
        "{label1: $label2}" +
    ") " +
    "YIELD value AS row " +
    "RETURN row",
    ImmutableMap.of("label2", "MyLabel")
);
System.out.println(result.next());

这将返回:

{row={keys=[attr1]}}

但同样,这是一个学术解决方案,我真的想不出一个最好的用例。

(与这个问题同时,还有一个APOC 问题的讨论。)

于 2017-10-08T05:12:04.260 回答
1

编辑

数据库存在被擦除的风险(请参阅下面@Gabor 的评论),但我仍然会沿着 Enum 的路线解决这个问题。但是,从那个 pov 来看,Gabor 的答案更好。


APOC 正在做与您相同的事情,因此您不会从使用它中获得任何好处。我认为这里的关键是查看您需要的保护级别。

接受您的查询,(我已经猜测了RETURN一下)归结为:

MATCH (n) WHERE n.Id = {p0} OPTIONAL MATCH (n)-[:{injectionPoint}]->(n1) RETURN n, n1

让我们看看我们可以从中得到什么,假设攻击者知道以下信息:

  • 您返回的格式(即您从n和获得的信息n1
  • 您的查询的结构如何,即知道您正在返回一个名为n1

他们可以尝试添加另一个查询,即注入如下内容:

"ORIGINAL]->(n1) RETURN n1; MATCH (n) RETURN labels(n);"

但这不起作用有两个原因,一是Cypher您调用的端点一次只能接受一个查询,二是来自MATCH (n) RETURN labels(n)的响应与您当前获得的响应不匹配,因此会出错。

您面临的最大风险是有人能够通过传递不同的关系类型直到他们得到响应来制定您的模型——但这需要很长时间,所以可能不是这样的问题。

攻击者确实必须知道上面的信息才能将其清除,否则,他们只会在黑暗中刺伤。如果他们确实有这些信息——那么他们可能已经知道他们可以从你的数据库中得到什么。

如果你把你正在做的事情放到一个 SQL 上下文中,你会从任何表中请求一些东西,带有一个 ID,然后通过提供一个表名,寻找任何连接到的东西。你会在 SQL 中这样做吗?此外 - 没有标签,您正在扫描整个数据库以获取此信息,这将非常慢。

我认为您最好至少向其中一个节点添加标签,如果不是同时添加标签,并使用 Enum 之类的东西来表示您允许的关系 - 我很欣赏这对于大量数字来说是不切实际的。

于 2017-10-09T11:50:12.710 回答