污点分析没有类作为其来源的非恒定场的流动路径

发布于 2025-02-08 06:54:15 字数 2325 浏览 1 评论 0原文

我有这个简单的测试课,我正在尝试模仿路径问题。 使用Message1作为源,console.writeline(Message1)作为接收器。

 class Test
    {
        private const string Message1 = "Test Message 1";
        private readonly string Message2 = "Test Message 2";

        public void Run()
        {
            Console.WriteLine(Message1);
            Console.WriteLine(Message2);
        }
    }
import csharp
import DataFlow::PathGraph

class Source extends DataFlow::Node {
  Source() { this.asExpr() instanceof StringLiteral }
}

class WriteLineMethod extends Method {
  WriteLineMethod() { this.hasQualifiedName("System.Console.WriteLine") }
}

class Sink extends DataFlow::Node {
  Sink() {
    exists(MethodCall m |
      m.getTarget() instanceof WriteLineMethod and
      this.asExpr() = m.getArgument(0)
    )
  }
}

class SimpleConfiguration extends TaintTracking::Configuration {
  SimpleConfiguration() { this = "Simple configuration" }

  override predicate isSource(DataFlow::Node source) { source instanceof Source }

  override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
  
}

from DataFlow::PathNode source, DataFlow::PathNode sink, SimpleConfiguration cfg
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ is used in WriteLine method.", source.getNode(),
  "String"

在这里,我使用上述查询在上述测试类上进行了简单的污点跟踪分析,用于const field private const字符串message1 =“ test message 1”;作为source> sourceconsole.writeline(Message1);作为sink我得到了正确的结果,但对于non Const field private ReadOnly ReadOnly String Messages2 = “测试消息2”; 似乎不起作用。

我在这里想念什么吗?为什么污点跟踪适用于静态类中的const字段或静态字段,而例如字段?

“测试。

数据库zip文件: -database

codeql- test 在下面的github/codeql上创建了一个问题,是一个链接供参考。

github/codeql/dessoce/9569

I have this simple Test class, where I'm trying to mimic a path problem.
with Message1 as source and Console.WriteLine(Message1) as sink.

 class Test
    {
        private const string Message1 = "Test Message 1";
        private readonly string Message2 = "Test Message 2";

        public void Run()
        {
            Console.WriteLine(Message1);
            Console.WriteLine(Message2);
        }
    }
import csharp
import DataFlow::PathGraph

class Source extends DataFlow::Node {
  Source() { this.asExpr() instanceof StringLiteral }
}

class WriteLineMethod extends Method {
  WriteLineMethod() { this.hasQualifiedName("System.Console.WriteLine") }
}

class Sink extends DataFlow::Node {
  Sink() {
    exists(MethodCall m |
      m.getTarget() instanceof WriteLineMethod and
      this.asExpr() = m.getArgument(0)
    )
  }
}

class SimpleConfiguration extends TaintTracking::Configuration {
  SimpleConfiguration() { this = "Simple configuration" }

  override predicate isSource(DataFlow::Node source) { source instanceof Source }

  override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
  
}

from DataFlow::PathNode source, DataFlow::PathNode sink, SimpleConfiguration cfg
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ is used in WriteLine method.", source.getNode(),
  "String"

Here I did simple taint tracking analysis on above Test class using above query, for const field private const string Message1 = "Test Message 1"; as source and
Console.WriteLine(Message1); as sink i'm getting correct result, But for non const field private readonly string Message2 = "Test Message 2"; it doesn't seem to work.

Did i miss something here? why does taint tracking works for const field or static field in static class but not for instance field?

test.ql result

Database zip file:
codeql-test-database

Edit:

I have created an issue for same at github/codeql below is an link for reference.

github/codeql/issues/9569

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是男神闪亮亮 2025-02-15 06:54:15

引用链接 to github讨论答案。

这是一个很好的问题,我不得不研究答案的CFG和DF​​实施详细信息,我不确定我是否有完整的图片,但希望以下答案可以回答您的问题。

codeql c#库处理实例字段与staticconst字段不同。当CFG构造时,实例字段的初始化器被移动为实例构造函数。因此以下样品

 类C 
{
  int x = 42;

  C(){}
}
 

在CFG

中以下面的形式建模

 类C
{
  int x;

  C() 
  {
    this.x = 42;
  }
}
 

我不确定它这样实现的原因,但是我认为这使我们可以在继承和虚拟派遣的情况下进行精确的数据流分析。另外,它会降低噪声:在您的示例中,实际上没有代码路径可以打印测试消息2,因为没有test test的实例 run()被调用。

基于上述CFG模型,为了找到丢失的流,我们需要添加一些代码,其中包括初始化和调用run()。因此,例如添加以下构造函数

  test()
{
  跑步();
}
 

有效,因为它已转换为

  test()
{
  this.message2 =“测试消息2”;
  this.run();
}
 

和基于字段的数据流程从String字面到Writeline this 实例。

引入缺失流的另一种方法是添加以下内容:

 静态void m()
{
  var t = new Test();
  t.run();
}

公共测试(){}
 

在这种情况下,CodeQl找到了实例t的流程。 (请注意,添加空构造函数不应是必需的,但是由于CFG结构中的错误,没有它的流程。我提交了内部问题来解决此问题。)

这是一个很好的问题,我不得不研究答案的CFG和DF​​实施详细信息,我不确定我是否有完整的图片,但希望以下答案可以回答您的问题。

codeql c#库处理实例字段与staticconst字段不同。当CFG构造时,实例字段的初始化器被移动为实例构造函数。因此以下样品

 类C 
{
  int x = 42;

  C(){}
}
 

在CFG

中以下面的形式建模

 类C
{
  int x;

  C() 
  {
    this.x = 42;
  }
}
 

我不确定它这样实现的原因,但是我认为这使我们可以在继承和虚拟派遣的情况下进行精确的数据流分析。另外,它会降低噪声:在您的示例中,实际上没有代码路径可以打印测试消息2,因为没有test test的实例 run()被调用。

基于上述CFG模型,为了找到丢失的流,我们需要添加一些代码,其中包括初始化和调用run()。因此,例如添加以下构造函数

  test()
{
  跑步();
}
 

有效,因为它已转换为

  test()
{
  this.message2 =“测试消息2”;
  this.run();
}
 

和基于字段的数据流程从String字面到Writeline this 实例。

引入缺失流的另一种方法是添加以下内容:

 静态void m()
{
  var t = new Test();
  t.run();
}

公共测试(){}
 

在这种情况下,CodeQl找到了实例t的流程。 (请注意,添加空构造函数不需要必要,但是由于CFG结构中的错误,如果没有它,就找不到流程。我提交了内部问题来解决此问题。)

Quoting this detailed analysis by tamasvajk and here is the link to github discussion answer.

This is a great question, I had to dig into CFG and DF implementation details for the answer, and I'm not sure I have the full picture yet, but hopefully the below answers your question.

The CodeQL C# library handles instance fields differently than static or const fields. Initializers of instance fields are moved into instance constructors when the CFG is constructed. So the following sample

class C 
{
  int x = 42;

  C() { }
}

is modelled as the below in the CFG

class C
{
  int x;

  C() 
  {
    this.x = 42;
  }
}

I'm not sure about the reasons why it was implemented like this, but I assume this lets us do precise dataflow analysis in case of inheritance and virtual dispatch. Also, it reduces noise: in your sample, there's actually no code path that would print Test Message 2, because there's no instance of Test on which Run() is invoked.

Based on the above CFG model, in order to find the missing flow, we need to add some code that includes the initialization and a call to Run(). So for example adding the following constructor

Test()
{
  Run();
}

works, because it is transformed to

Test()
{
  this.Message2 = "Test Message 2";
  this.Run();
}

and there's field based dataflow from the string literal to WriteLine on the this instance.

Another way to introduce the missing flow would be adding the following:

static void M()
{
  var t = new Test();
  t.Run();
}

public Test() { }

In this case CodeQL finds the flow for instance t. (Note that adding the empty constructor should not be necessary, but due to a bug in the CFG construction, the flow is not found without it. I submitted an internal issue to fix this.)

This is a great question, I had to dig into CFG and DF implementation details for the answer, and I'm not sure I have the full picture yet, but hopefully the below answers your question.

The CodeQL C# library handles instance fields differently than static or const fields. Initializers of instance fields are moved into instance constructors when the CFG is constructed. So the following sample

class C 
{
  int x = 42;

  C() { }
}

is modelled as the below in the CFG

class C
{
  int x;

  C() 
  {
    this.x = 42;
  }
}

I'm not sure about the reasons why it was implemented like this, but I assume this lets us do precise dataflow analysis in case of inheritance and virtual dispatch. Also, it reduces noise: in your sample, there's actually no code path that would print Test Message 2, because there's no instance of Test on which Run() is invoked.

Based on the above CFG model, in order to find the missing flow, we need to add some code that includes the initialization and a call to Run(). So for example adding the following constructor

Test()
{
  Run();
}

works, because it is transformed to

Test()
{
  this.Message2 = "Test Message 2";
  this.Run();
}

and there's field based dataflow from the string literal to WriteLine on the this instance.

Another way to introduce the missing flow would be adding the following:

static void M()
{
  var t = new Test();
  t.Run();
}

public Test() { }

In this case CodeQL finds the flow for instance t. (Note that adding the empty constructor should not be necessary, but due to a bug in the CFG construction, the flow is not found without it. I submitted an internal issue to fix this.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文