Maison > Article > Opération et maintenance > Comment Codeql analyse le problème des cookies n'activant pas httponly
Aujourd'hui, nous utilisons codeql pour analyser les problèmes de sécurité tels que "le cookie n'est pas activé http uniquement", approfondissant ainsi notre utilisation de codeql. Si cela fonctionne bien, vous pouvez envisager de corriger d'autres vulnérabilités dans Vulnerability-goapp.
Vous devez en outre télécharger codeql-go lors de l'analyse des programmes go
Vulnérabilité-goapp : application Web golang vulnérable pour l'éducation.
Étant donné que tous les cookies de ce projet n'ont pas l'attribut http uniquement défini, nous devons d'abord les modifier avant la comparaison. Ce qui suit est une réécriture de la phrase originale : Modification de l'enregistrement : ajoutez l'option http uniquement à certains paramètres de cookies.
pkgadminadmin.go est modifié comme suit.
pkgloginlogin.go est modifié comme suit.
pkgregisterregister.go est modifié comme suit.
N'oubliez pas de régénérer la base de données après modification (si vous devez écraser l'ancienne base de données, vous devez d'abord supprimer l'ancienne puis en générer une nouvelle.
est d'utiliser le script codeql pour trouver que httponly n'est pas défini et httponly est défini) Mais la valeur de httponly est fausse (généralement ce n'est pas le cas, mais ce n'est pas garanti
Le puits est très simple). Lors de la définition des cookies, vous devez utiliser la méthode http.SetCookie. La valeur du cookie qui doit être définie est le deuxième paramètre de cette fonction, puis nous pouvons écrire une instruction de requête pour trouver un récepteur comme celui-ci
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. en cours d'exécution, vous pouvez obtenir les résultats suivants. En cliquant sur n'importe quel élément, vous accéderez à l'exigence composée sous le segment de code
Nous le convertissons en classe Sink, comme suit
private class Sink extends DataFlow::Node { Sink() { exists(DataFlow::CallNode c | c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this ) } }
Après cela, en définissant une variable. comme Sink, il fait référence à tous les extraits de code qui remplissent les conditions, par exemple :
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
Après l'exécution Le même résultat sera obtenu
Ensuite, nous déterminons la source à en juger par les paramètres reçus par http. Méthode SetCookie, le deuxième paramètre réel est un pointeur vers la structure d'un Cookie
Donc, nous devons d'abord trouver une telle structure. Nous pouvons d'abord lister toutes les structures du projet. codeql-go est le suivant
Donc, notre script de requête est également
import go from StructLit source select source
Toutes les structures sont répertoriées comme prévu
Ensuite, l'étape suivante consiste à éliminer les autres contenus non pertinents et à restreindre les types. la méthode hasQualifiedName, différents types dans Codeql-go. Ils ont tous la même méthode, définie comme suit, à quel package appartient l'objet et quel est son nom
Si vous n'êtes pas sûr, vous pouvez imprimer les champs pertinents. via getPackage et getName, par exemple
import go from StructLit source // where source.getType().hasQualifiedName("net/http", "Cookie") select source.getType().getPackage(), source.getType().getName()Les résultats sont les suivants Nous pouvons trouver la définition source, par exemple
import go from StructLit source where source.getType().hasQualifiedName("net/http", "Cookie") select source
private class Source extends DataFlow::Node { Source() { exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s) } }
TaintConfig.
Flux de données simple
Avec Source et Sink, définissez simplement TaintConfig. Tous les flux de données de la source vers le Sink peuvent être obtenusimport 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
Cependant, nous n'avons pas encore supprimé. la partie où httponly=true est défini, nous devons donc ajouter la qualification, qui est sur le point d'avoir l'attribut HttpOnly. Les flux de données qui sont vrais sont exclus des résultats
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 ) }
运行结果如下,但有一处地方需要注意。
红框中实际有对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"
最终筛选出存在问题的内容。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!