热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何防止C#中的Gremlin注射?

如何解决《如何防止C#中的Gremlin注射?》经验,为你挑选了1个好方法。

当用户在文本框中输入数据时,会观察到SQL注入的许多可能性.为了防止这种情况,许多方法可用于在SQL查询中使用占位符,这些方法将在输入的下一步代码中替换.同样,我们如何在C#中防止Gremlin Injection?

示例:以下是在图形数据库中添加节点的示例代码.变量的值:name和nodeId是通过文本框从用户获取的.

StringBuilder sb = new StringBuilder();
sb.Append("g.addV('" + name + "').property('id','"+nodeId+"')");

/*The following simply executes the gremlin query stored in sb*/

IDocumentQuery query = client.CreateGremlinQuery(graph, sb.ToString());
while (query.HasMoreResults){
   foreach (dynamic result in await query.ExecuteNextAsync())
    {
       Console.WriteLine($"\t {JsonConvert.SerializeObject(result)}");
    }}

恶意用户可以编写attributeValue之类的

名称: "人"(不含引号)

id: "mary"); gV().drop(); g.addV('person').property('id','thomas'(不含引号)

这将清除所有现有节点,并仅添加一个id为:thomas的节点

我该如何防止这种情况发生?

我不希望将";"等字符列入黑名单 或")"因为这可以作为某些数据的输入.

注意:Gremlin是图形数据库中使用的遍历语言:

https://tinkerpop.apache.org/gremlin.html

https://docs.microsoft.com/en-us/azure/cosmos-db/gremlin-support



1> Florian Hock..:

问题最初是关于Gremlin注入的情况,其中Gremlin遍历以查询脚本的形式发送到服务器(例如,Gremlin Server).我在这个场景的原始答案可以在下面找到(Gremlin Scripts).但是,到目前为止,Gremlin语言变体是执行Gremlin遍历的主要方式,这就是为什么我扩展我的答案,因为它与简单的Gremlin脚本的情况非常不同.

Gremlin语言变体

Gremlin语言变体(GLV)是Gremlin在不同主机语言(如Python,Javascript或C#)中的实现.这意味着不要将遍历作为字符串发送到服务器

client.SubmitAsync("g.V().count");

它可以简单地表示为特定语言的代码,然后使用特殊的终端步骤(如next()iterate())执行:

g.V().Count().Next();

这构建并执行C#中的遍历(在其他语言中看起来基本相同,只是在pascal情况下不是步骤名称).遍历将转换为Gremlin字节码,这是Gremlin遍历的语言无关表示.然后将此字节序列化为GraphSON,以发送到服务器进行评估:

{
  "@type" : "g:Bytecode",
  "@value" : {
    "step" : [ [ "V" ], [ "count" ] ]
  }
}

这个非常简单的遍历已经表明GraphSON包含类型信息,特别是自版本2.0以及版本3.0以来更多,这是自TinkerPop 3.3.0以来的默认版本.

攻击者有两种有趣的GraphSON类型,即已经显示的Bytecode可用于执行Gremlin遍历,例如g.V().drop操作/删除图中的数据,以及g:Lambda可用于执行任意代码1的数据:

{
  "@type" : "g:Lambda",
  "@value" : {
    "script" : "{ it.get() }",
    "language" : "gremlin-groovy",
    "arguments" : 1
  }
}

但是,攻击者需要将自己的字节码或lambda作为参数添加到现有遍历的一个步骤中.由于字符串只是在GraphSON中被序列化为字符串,无论它是否包含表示lambda或Bytecode的字符串,因此无法以这种方式将代码注入到具有GLV的Gremlin遍历中.代码将简单地视为字符串.这可行的唯一方法是攻击者能够直接向该步骤提供字节码或Lambda对象,但我想不出任何允许这种情况的场景.

因此,据我所知,当使用GLV时,无法将代码注入Gremlin遍历.这与使用或不使用绑定的事实无关.


以下部分是将遍历作为查询字符串发送到服务器的方案的原始答案:

Gremlin脚本

你的例子确实会产生一些你可以称之为Gremlin注射的东西.我用Gremlin.Net测试了它,但它应该与任何Gremlin驱动程序一样工作.这是测试,证明注射实际上是有效的:

var gremlinServer = new GremlinServer("localhost");
using (var gremlinClient = new GremlinClient(gremlinServer))
{
    var name = "person";
    var nodeId = "mary').next();g.V().drop().iterate();g.V().has('id', 'thomas";
    var query = "g.addV('" + name + "').property('id','" + nodeId + "')";

    await gremlinClient.SubmitAsync(query);

    var count = await gremlinClient.SubmitWithSingleResultAsync(
        "g.V().count().next()");
    Assert.NotEqual(0, count);
}

因为这个测试失败count0这表明小鬼服务器执行的g.V().drop().iterate()穿越.

脚本参数化

现在官方的TinkerPop文档建议使用脚本参数化,而不是简单地将参数直接包含在查询脚本中,就像我们在前面的示例中所做的那样.虽然它通过性能改进激发了这一建议,但它也有助于防止恶意用户输入的注入.要了解脚本参数化的效果,我们必须查看如何将请求发送到Gremlin服务器(取自提供者文档):

{ "requestId":"1d6d02bd-8e56-421d-9438-3bd6d0079ff1",
  "op":"eval",
  "processor":"",
  "args":{"gremlin":"g.traversal().V(x).out()",
          "bindings":{"x":1},
          "language":"gremlin-groovy"}}

正如我们在请求消息的JSON表示中所看到的,Gremlin脚本的参数作为绑定与脚本本身分开发送.(该参数x在此处命名并具有值1.)这里重要的是Gremlin Server将仅从gremlin元素执行脚本,然后将元素中的参数bindings作为原始值包含在内.

一个简单的测试,看看使用绑定可以防止注入:

var gremlinServer = new GremlinServer("localhost");
using (var gremlinClient = new GremlinClient(gremlinServer))
{
    var name = "person";
    var nodeId = "mary').next();g.V().drop().iterate();g.V().has('id', 'thomas";
    var query = "g.addV('" + name + "').property('id', nodeId)";
    var arguments = new Dictionary
    {
        {"nodeId", nodeId}
    };

    await gremlinClient.SubmitAsync(query, arguments);

    var count = await gremlinClient.SubmitWithSingleResultAsync(
        "g.V().count().next()");
    Assert.NotEqual(0, count);

    var existQuery = $"g.V().has('{name}', 'id', nodeId).values('id');";
    var nodeIdInDb = await gremlinClient.SubmitWithSingleResultAsync(existQuery, 
        arguments);
    Assert.Equal(nodeId, nodeIdInDb);
}

此测试不仅显示g.V().drop()未执行的测试(否则count将再次具有该值0),但它还在最后三行中演示了注入的Gremlin脚本仅用作id属性的值.


1这种任意代码执行实际上是提供者特定的.例如,像Amazon Neptune 这样的提供商根本不支持lambdas,也可以限制可以使用SandboxExtension为Gremlin Server执行的代码,例如,通过将已知有问题的方法列入黑名单,使用SimpleSandboxExtension或仅通过白名单FileSandboxExtension的无问题方法.


推荐阅读
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
author-avatar
henkoanna
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有