Home  >  Article  >  Operation and Maintenance  >  How Codeql analyzes the problem of cookie not enabling httponly

How Codeql analyzes the problem of cookie not enabling httponly

PHPz
PHPzforward
2023-05-17 17:25:591255browse

Preface

Today we use codeql to analyze security issues such as "cookie is not enabled httponly", thereby deepening our use of codeql. If it works well, you can consider fixing other vulnerabilities in Vulnerability-goapp.

You must additionally download codeql-go when analyzing go programs

Instructions

Audit objects

Vulnerability-goapp: Vulnerable golang Web application for education.

Modification

Since all cookies in this project do not have the http-only attribute set, we need to modify them first before comparison. The following is a rewrite of the original sentence: Record modification: Add http-only option to some cookie settings.

pkg\admin\admin.go is modified as follows.
How Codeql analyzes the problem of cookie not enabling httponly

pkg\login\login.go is modified as follows.
How Codeql analyzes the problem of cookie not enabling httponly

pkg\register\register.go is modified as follows.
How Codeql analyzes the problem of cookie not enabling httponly

Remember to regenerate the database after modification (if you need to overwrite the old DATabase, you need to delete the old one first and then generate a new one.

Purpose

It is to use the codeql script to find the loopholes in which httponly is not set and httponly is set but the value of httponly is false (usually this is not the case, but it is not guaranteed).

Determine the Source and Sink

Sink definition

Sink is very simple. When setting Cookie, you need to use the http.SetCookie method, and the Cookie value that needs to be set is the second parameter of this function, and then we can write Find the query statement of Sink like this.

import go
from DataFlow::Node sink
where exists(DataFlow::CallNode c |
      c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = sink
    )
select sink

After running, you can get the following results. Click on any item to jump to the code segment of the compound requirement.
How Codeql analyzes the problem of cookie not enabling httponly

We will It is converted into a Sink class, as follows.

private class Sink extends DataFlow::Node {
  Sink() {
    exists(DataFlow::CallNode c |
      c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this
    )
  }
}

In this way, if we define a variable as Sink, it refers to all code fragments that meet the conditions, for example:

import go

private class Sink extends DataFlow::Node {
  Sink() {
    exists(DataFlow::CallNode c |
      c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this
    )
  }
}

from Sink s
select s

After running, we will get The same result.

Source definition

Then let’s determine the Source. Judging from the parameters received by the http.SetCookie method, the actual second parameter is a pointer to the structure that receives a Cookie.
How Codeql analyzes the problem of cookie not enabling httponlyHow Codeql analyzes the problem of cookie not enabling httponly

So we first need to find such a structure. We can first list all the structures in the project.

About the structure in codeql-go The definition of the body is as follows.
How Codeql analyzes the problem of cookie not enabling httponly

So our query script for example.

import go

from StructLit source
select source

also lists all the structures as we expected.
How Codeql analyzes the problem of cookie not enabling httponly

Then the next step is to eliminate other irrelevant content and restrict the type.

Regarding the hasQualifiedName method, various types in various Codeql-go have the same method. The definition is as follows. The marked object belongs to which package and what is its name.
How Codeql analyzes the problem of cookie not enabling httponly

If you are not sure, you can print the relevant fields through getPackage and getName, for example.

import go

from StructLit source
// where source.getType().hasQualifiedName("net/http", "Cookie")
select source.getType().getPackage(), source.getType().getName()

The results are as follows.
How Codeql analyzes the problem of cookie not enabling httponly

We can find the source definition, for example.

import go

from StructLit source
where source.getType().hasQualifiedName("net/http", "Cookie")
select source

How Codeql analyzes the problem of cookie not enabling httponlyIt is also converted into a subclass of DataFlow::Node.

private class Source extends DataFlow::Node {
  Source() {
    exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s)
  }
}

TaintConfig definition

Simple data flow

With Source and Sink, simply define TaintConfig to get all the data flow from Source to Sink.

import go

private class Source extends DataFlow::Node {
  Source() {
    exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s)
  }
}

private class Sink extends DataFlow::Node {
  Sink() {
    exists(DataFlow::CallNode c |
      c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this
    )
  }
}

class Configuration extends TaintTracking::Configuration {
  Configuration() { this = "HttpOnly" }

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

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

from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select source, sink

The results are as follows:
How Codeql analyzes the problem of cookie not enabling httponly

Elimination

However, we still have not removed the part where httponly=true is set. Therefore, it is necessary to add limiting conditions, that is, data streams with the HttpOnly attribute set to true are excluded from the results.

We can use TaintTracking::isSanitizer provided by CodeQL to filter harmless nodes:

override predicate isSanitizer(DataFlow::Node node) {
    exists(Write w, Field f, DataFlow::Node rhs |
      f.hasQualifiedName("net/http", "Cookie", "HttpOnly") and
      w.writesField(node, f, rhs) and
      rhs.getBoolValue() = true
    )
  }

运行结果如下,但有一处地方需要注意。
How Codeql analyzes the problem of cookie not enabling httponly红框中实际有对HttpOnly进行设置,但我们的脚本并不能识别这样的一个数据流。后面试了各种方法,最终找到一种解决方式,将isSanitizer修改成以下内容。

override predicate isSanitizer(DataFlow::Node node) {
    exists(Write w, Field f, DataFlow::Node n, DataFlow::Node rhs |
      f.hasQualifiedName("net/http", "Cookie", "HttpOnly") and
      w.writesField(n, f, rhs) and
      rhs.getBoolValue() = true and
      node = n.getAPredecessor*()n
    )
  }

其中node=n.getAPredecessor*()是说node是n的前置数据流节点,数据可以在0个或多个步骤中从node流到n。

最终脚本

加上一些信息,模仿官方的示例,最终脚本如下。

/**
 * @name Cookie未设置httponly
 * @description Cookies包含一个HTTPOnly的设置选项,可以使此cookie不能被js读取,而只能用于HTTP请求。
 * @kind path-problem
 * @problem.severity error
 * @precision low
 * @id go/Cookie-not-set-httponly
 * @tags security
 */

import go
import DataFlow::PathGraph

private class Source extends DataFlow::Node {
  Source() {
    exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s)
  }
}

private class Sink extends DataFlow::Node {
  Sink() {
    exists(DataFlow::CallNode c |
      c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this
    )
  }
}

class Configuration extends TaintTracking::Configuration {
  Configuration() { this = "HttpOnly" }

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

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

  override predicate isSanitizer(DataFlow::Node node) {
    exists(Write w, Field f, DataFlow::Node n, DataFlow::Node rhs |
      f.hasQualifiedName("net/http", "Cookie", "HttpOnly") and
      w.writesField(n, f, rhs) and
      rhs.getBoolValue() = true and
      node = n.getAPredecessor*()
    )
  }
}

from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Cookie-not-set-httponly in $@.", source.getNode(), "here"

最终筛选出存在问题的内容。
How Codeql analyzes the problem of cookie not enabling httponly

The above is the detailed content of How Codeql analyzes the problem of cookie not enabling httponly. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete