ホームページ  >  記事  >  運用・保守  >  Codeql が Cookie が httponly を有効にしない問題を分析する方法

Codeql が Cookie が httponly を有効にしない問題を分析する方法

PHPz
PHPz転載
2023-05-17 17:25:591276ブラウズ

はじめに

今日は、codeql を使用して「Cookie が httponly で有効になっていない」などのセキュリティ問題を分析し、codeql の使用法を深めます。うまく機能する場合は、Vulnerability-goapp の他の脆弱性を修正することを検討できます。

go プログラムを分析する場合は、codeql-go をさらにダウンロードする必要があります

手順

監査オブジェクト

Vulnerability-goapp: 教育用の脆弱な golang Web アプリケーション。

変更

このプロジェクトのすべての Cookie には http のみの属性が設定されていないため、比較する前にまずそれらを変更する必要があります。以下は元の文を書き直したものです。 レコードの変更: 一部の Cookie 設定に http のみのオプションを追加します。

pkg\admin\admin.go を次のように変更します。
Codeql が Cookie が httponly を有効にしない問題を分析する方法

pkg\login\login.go を次のように変更します。
Codeql が Cookie が httponly を有効にしない問題を分析する方法

pkg\register\register.go を次のように変更します。
Codeql が Cookie が httponly を有効にしない問題を分析する方法

変更後に必ずデータベースを再生成してください (古い DATAbase を上書きする必要がある場合は、まず古い DATAbase を削除してから、新しい DATAbase を生成する必要があります。

目的

codeql スクリプトを使用して、httponly が設定されていない、および httponly が設定されているが httponly の値が false である抜け穴を見つけることです (通常はそうではありませんが、保証されません)。

ソースとシンクの決定

シンクの定義

シンクは非常にシンプルで、Cookie を設定するときは、http.SetCookie メソッドを使用する必要があります。設定するのはこの関数の 2 番目のパラメータで、Sink のクエリ ステートメントを次のように記述します。

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

実行後、次の結果が得られます。任意の項目をクリックすると、その項目にジャンプします。
Codeql が Cookie が httponly を有効にしない問題を分析する方法

次のように Sink クラスに変換されます

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

このように変数を Sink として定義すると例:

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

実行後、同じ結果が得られます。

ソース定義

次に、ソース。http.SetCookie メソッドで受け取ったパラメータから判断すると、実際の 2 番目のパラメータは、Cookie を受け取る構造体へのポインタです。
Codeql が Cookie が httponly を有効にしない問題を分析する方法Codeql が Cookie が httponly を有効にしない問題を分析する方法

したがって、最初に見つける必要があります。まずはプロジェクト内のすべての構造をリストします。

codeql-go の構造について本文の定義は次のとおりです。たとえば、クエリ スクリプトです。

import go

from StructLit source
select source
Codeql が Cookie が httponly を有効にしない問題を分析する方法 には、予想どおりすべての構造もリストされています。

次に、他の無関係なコンテンツを削除し、タイプを制限します。
Codeql が Cookie が httponly を有効にしない問題を分析する方法 hasQualifiedName メソッドについては、さまざまな Codeql-go のさまざまな型が同じメソッドを持っていますが、定義は次のようになります マークされたオブジェクトはどのパッケージに属し、その名前は何であるかということです。

よくわからない場合は、たとえば getPackage や getName を通じて関連するフィールドを出力できます。

import go

from StructLit source
// where source.getType().hasQualifiedName("net/http", "Cookie")
select source.getType().getPackage(), source.getType().getName()
結果は次のとおりです。


Codeql が Cookie が httponly を有効にしない問題を分析する方法

たとえば、ソース定義を見つけます。

import go

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

DataFlow::Node のサブクラスにも変換されます。

private class Source extends DataFlow::Node {
  Source() {
    exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s)
  }
}
Codeql が Cookie が httponly を有効にしない問題を分析する方法TaintConfig 定義

単純なデータ フロー

Source と Sink では、TaintConfig を定義するだけで、Source から Sink へのすべてのデータ フローを取得できます。 Codeql が Cookie が httponly を有効にしない問題を分析する方法

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
結果は次のとおりです。

削除

ただし、httponly=true が設定されている部分はまだ削除されていません。したがって、制限条件を追加する必要があります。つまり、HttpOnly 属性が true に設定されているデータ ストリームを結果から除外します。


CodeQL が提供する TaintTracking::isSanitizer を使用して、無害なノードをフィルタリングできます: Codeql が Cookie が httponly を有効にしない問題を分析する方法

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
    )
  }

运行结果如下,但有一处地方需要注意。
Codeql が Cookie が 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"

最终筛选出存在问题的内容。
Codeql が Cookie が httponly を有効にしない問題を分析する方法

以上がCodeql が Cookie が httponly を有効にしない問題を分析する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。