本篇文章給大家分享的是有關(guān)Codeql如何分析cookie未啟用httponly的問(wèn)題,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。
10年積累的網(wǎng)站制作、成都網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶(hù)對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶(hù)得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有潛山免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
今天我們利用codeql分析下“cookie未啟用httponly“這類(lèi)的安全問(wèn)題,由此加深自己對(duì)codeql的使用。如果反應(yīng)好的話,可以考慮把Vulnerability-goapp的其他漏洞也弄一弄。
分析go程序時(shí)必須額外下載codeql-go
Vulnerability-goapp:Vulnerable golang Web application for education。
因?yàn)樵擁?xiàng)目中的所有cookie均未設(shè)置http-only,沒(méi)有對(duì)比性,所以我們先要對(duì)其修改。在一些cookie設(shè)置中添加上http-only,修改記錄如下。
pkg\admin\admin.go修改如下。
pkg\login\login.go修改如下。
pkg\register\register.go修改如下。
修改后記得重新生成一次database(如果需要覆蓋舊的DATabase的話,則需要先刪除舊的再生成新的。
就是通過(guò)codeql腳本來(lái)發(fā)現(xiàn)其中未設(shè)置httponly和設(shè)置了httponly的但httponly的值為false(一般不會(huì)這樣,但保不齊有)的這樣存在漏洞的點(diǎn)。
Sink很簡(jiǎn)單,設(shè)置Cookie時(shí),需要用到http.SetCookie方法,而需要設(shè)置的Cookie值是這個(gè)函數(shù)的第二個(gè)參數(shù),然后我們可以寫(xiě)出找到類(lèi)似這樣Sink的查詢(xún)語(yǔ)句。
import go from DataFlow::Node sink where exists(DataFlow::CallNode c | c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = sink ) select sink
運(yùn)行后可獲得以下結(jié)果,點(diǎn)擊任意條目都會(huì)跳轉(zhuǎn)到復(fù)合要求的代碼段下。
我們將其轉(zhuǎn)換成一個(gè)Sink類(lèi),如下。
private class Sink extends DataFlow::Node { Sink() { exists(DataFlow::CallNode c | c.getTarget().hasQualifiedName("net/http", "SetCookie") and c.getArgument(1) = this ) } }
這樣之后我們通過(guò)將一個(gè)變量定義成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
運(yùn)行后會(huì)獲得同樣的結(jié)果。
然后我們?cè)賮?lái)確定Source,從http.SetCookie方法接收的參數(shù)來(lái)看,實(shí)際第二個(gè)參數(shù)是接收一個(gè)Cookie的結(jié)構(gòu)體的指針。
所以我們先要找到這樣一個(gè)結(jié)構(gòu)體,我們可以先把項(xiàng)目中所有的結(jié)構(gòu)體列出來(lái)。
codeql-go中關(guān)于結(jié)構(gòu)體的定義如下。
所以我們的查詢(xún)腳本例如。
import go from StructLit source select source
也如我們預(yù)期的一樣列出了所有的結(jié)構(gòu)體。
然后接下來(lái)就是剔除其他不相干的內(nèi)容,對(duì)類(lèi)型做限制。
關(guān)于hasQualifiedName方法,在各種Codeql-go中的各種類(lèi)型都有相同的方法,定義如下,標(biāo)記對(duì)象的是在屬于哪個(gè)包,叫什么名。
如果不確定的話,可以通過(guò),getPackage和getName打印相關(guān)字段,例如。
import go from StructLit source // where source.getType().hasQualifiedName("net/http", "Cookie") select source.getType().getPackage(), source.getType().getName()
結(jié)果如下。
我們可以找到source定義,例如。
import go from StructLit source where source.getType().hasQualifiedName("net/http", "Cookie") select source
同樣轉(zhuǎn)換成DataFlow::Node的子類(lèi)。
private class Source extends DataFlow::Node { Source() { exists(StructLit s | s.getType().hasQualifiedName("net/http", "Cookie") and this.asExpr() = s) } }
有了Source和Sink,簡(jiǎn)單定義TaintConfig,就能獲得所有從Source到Sink的數(shù)據(jù)流。
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
結(jié)果如下:
但是還沒(méi)完,我們并沒(méi)有將設(shè)置了httponly=true的部分給剔除。所以需要增加限定,就是將給HttpOnly字段設(shè)置了true的數(shù)據(jù)流,從結(jié)果中剔除。
我們可以 CodeQL 提供的 TaintTracking::isSanitizer,來(lái)過(guò)濾無(wú)害節(jié)點(diǎn):
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 ) }
運(yùn)行結(jié)果如下,但有一處地方需要注意。
紅框中實(shí)際有對(duì)HttpOnly進(jìn)行設(shè)置,但我們的腳本并不能識(shí)別這樣的一個(gè)數(shù)據(jù)流。后面試了各種方法,最終找到一種解決方式,將isSanitizer修改成以下內(nèi)容。
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*()
是說(shuō)node是n的前置數(shù)據(jù)流節(jié)點(diǎn),數(shù)據(jù)可以在0個(gè)或多個(gè)步驟中從node流到n。
加上一些信息,模仿官方的示例,最終腳本如下。
/** * @name Cookie未設(shè)置httponly * @description Cookies包含一個(gè)HTTPOnly的設(shè)置選項(xiàng),可以使此cookie不能被js讀取,而只能用于HTTP請(qǐng)求。 * @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"
最終篩選出存在問(wèn)題的內(nèi)容。
以上就是Codeql如何分析cookie未啟用httponly的問(wèn)題,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。