当前位置:   article > 正文

codeql使用指南

codeql

目录

简介

hello world

1、安装codeql-cli 和 ql库

2、创建源码数据库

3、编写hello world

4、执行查询

进阶

1、扫描结果快速定位到源码

2、用作白盒扫描器

3、开发自己的查询代码

4、分析GitHub上的开源项目

​5、语法规则学习

codeql安全能力

java

实战

宽泛的跨域配置


简介

codeql是一门类似SQL的查询语言,通过对项目源码(C/C++、C#、golang、java、JavaScript、typescript、python)进行完整编译,并在此过程中把项目源码文件的所有相关信息(调用关系、语法语义、语法树)存在数据库中,然后编写代码查询该数据库来发现安全漏洞(硬编码/XSS等)

 

hello world

1、安装codeql-cli 和 ql库

codeql-cli是执行文件,ql库是已经写好的可以查询安全漏洞的代码

下载地址:

codeql-cli:https://github.com/github/codeql-cli-binaries/releases

ql库:https://github.com/github/codeql/releases

 

两个下载的zip文件务必解压在同一目录(codeql-home)下(因为codeql-cli把同层目录作为查找路径),并将codeql-cli放在系统目录中(Linux添加export PATH=$PATH:/home/f/.local/bin:/mnt/c/Users/xx/codeql-home/codeql-cli到.bashrc文件末尾)

 

2、创建源码数据库

首先clone项目源码:git clone https://github.com/XiaoMi/galaxy-sdk-java.git

然后创建源码数据库:codeql database create source_database_name  --language=java

 

3、编写hello world

下载的ql库是codeql代码,有包结构/目录结构要求(qlpack.yml定义一个package),才能正常编译、执行。

 

java语言的漏洞查询代码目录在qllib/java/ql/src/Security/CWE,这里新建test.ql(qllib/java/ql/src/Security/test/test.ql)查询源码,内容:

  1. /**
  2.  * @name sectest2
  3.  * @description Writing sectest33
  4.  * @kind problem
  5.  * @problem.severity error
  6.  * @precision high
  7.  * @id java/sectest
  8.  * @tags security
  9.  *       external/cwe/cwe-113
  10.  */
  11. import java
  12. from Parameter p
  13. where not exists(p.getAnAccess())
  14. select p, "no used param"

test.ql用来查询函数参数未使用的函数

 

4、执行查询

执行了查询代码之后,输出的内容即有漏洞的项目源代码

 

命令行执行:codeql database analyze source_database_name qllib/java/ql/src/Security/test/test.ql --format=csv --output=java-results.csv

 

查询发现的漏洞会输出到java-results.csv文件

 

 

进阶

1、扫描结果快速定位到源码

命令行方式执行查询,多少有些不便,使用vscode codeql插件则方便的多

安装完插件,需要在插件中指定待查询的源码库(第2步产生的文件夹),

然后在vscode中打开test.ql,右键运行查询,结果会自动打开

2、用作白盒扫描器

ql库集成了许多常见的安全漏洞(参考:https://codeql.github.com/codeql-query-help/java/),可以拿来扫描项目源码

 

codeql analyze命令可以执行单个ql文件,目录下所有ql文件,和查询suite(.qls)

 

白盒扫描使用如下命令(执行所有漏洞类查询)

codeql database analyze source_database_name qllib/java/ql/src/codeql-suites/java-security-extended.qls --format=csv --output=java-results.csv

 

3、开发自己的查询代码

ql入门:https://codeql.github.com/docs/writing-codeql-queries/introduction-to-ql/

各语言文档:https://codeql.github.com/docs/codeql-language-guides/abstract-syntax-tree-classes-for-working-with-java-programs/

 

目前codeql文档较少,只能照已有的规则进行模仿

qll文件是库文件,有很多函数可以直接import使用;qhelp是帮助说明文件;

 

ql文件(qllib/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql)如下:

注释部分是meta信息(都有重要作用,比如tags可以用来归属规则suites),

import同其他编程语言类似,可以导入现成的函数使用(qllib/java/ql/src/semmle/code/java)

from用来定义变量,where是判断规则,select是输出

  1. /**
  2.  * @name Failure to use secure cookies
  3.  * @description Insecure cookies may be sent in cleartext, which makes them vulnerable to
  4.  *              interception.
  5.  * @kind problem
  6.  * @problem.severity error
  7.  * @precision high
  8.  * @id java/insecure-cookie
  9.  * @tags security
  10.  *       external/cwe/cwe-614
  11.  */
  12. import java
  13. import semmle.code.java.frameworks.Servlets
  14. from MethodAccess add
  15. where
  16.   add.getMethod() instanceof ResponseAddCookieMethod and
  17.   not exists(Variable cookie, MethodAccess m |
  18.     add.getArgument(0) = cookie.getAnAccess() and
  19.     m.getMethod().getName() = "setSecure" and
  20.     m.getArgument(0).(BooleanLiteral).getBooleanValue() = true and
  21.     m.getQualifier() = cookie.getAnAccess()
  22.   )
  23. select add, "Cookie is added to response without the 'secure' flag being set."

 

有两类查询alert和path,从ql文件中的@kind problem/path-problem分辨,alert查询select返回两个字段(qllib/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql,select element, string),path查询(污点查找)select返回4个字段(qllib/java/ql/src/Security/CWE/CWE-079/XSS.ql,select element, source, sink, string),path查询带有调用链

 

4、分析GitHub上的开源项目

直接搜索即可

https://lgtm.com/search?q=xiaomi

 

https://lgtm.com/projects/g/XiaoMi/minos/?mode=list&result_filter=0e00f5fa7b93849767c1677dc71d9400f85c6a54

该开源项目存在xss漏洞:https://github.com/XiaoMi/minos/issues/43

 

 

​5、语法规则学习

①定义类/方法

  1. /**
  2. * A class that has `javax.servlet.Servlet` as an ancestor.
  3. */
  4. class ServletClass extends Class {
  5. ServletClass() { getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") }
  6. }

方法

  1. /**
  2. * The interface `javax.servlet.http.HttpServletResponse`.
  3. */
  4. class HttpServletResponse extends RefType {
  5. HttpServletResponse() { hasQualifiedName("javax.servlet.http", "HttpServletResponse") }
  6. }
  7. /**
  8. * The method `addCookie(Cookie)` declared in `javax.servlet.http.HttpServletResponse`.
  9. */
  10. class ResponseAddCookieMethod extends Method {
  11. ResponseAddCookieMethod() {
  12. getDeclaringType() instanceof HttpServletResponse and
  13. hasName("addCookie")
  14. }
  15. }
  16. //========================
  17. /** The class `java.lang.String`. */
  18. class TypeString extends Class {
  19. TypeString() { this.hasQualifiedName("java.lang", "String") }
  20. }
  21. /**
  22. * The method `getHeader(String)` declared in `javax.servlet.http.HttpServletRequest`.
  23. */
  24. library class HttpServletRequestGetHeaderMethod extends Method {
  25. HttpServletRequestGetHeaderMethod() {
  26. getDeclaringType() instanceof HttpServletRequest and
  27. hasName("getHeader") and
  28. getNumberOfParameters() = 1 and
  29. getParameter(0).getType() instanceof TypeString
  30. }
  31. }

②查询所有外部输入

  1. import java
  2. import semmle.code.java.dataflow.FlowSources
  3. from RemoteFlowSource rls
  4. select rls, "t:"+rls.getSourceType()

③获取所有外部依赖

  1. /**
  2.  * @name dependency version
  3.  * @description version with vulnerabilities
  4.  * @kind problem
  5.  * @problem.severity error
  6.  * @precision high
  7.  * @id java/dependency-version
  8.  * @tags security
  9.  *       external/cwe/cwe-113
  10.  */
  11. import java
  12. import semmle.code.xml.MavenPom
  13. predicate getCompileDependency(PomDependency dependency) {
  14.   dependency.getScope() = "compile" or dependency.getScope() = "runtime"
  15.   }
  16.   
  17.   from PomDependency dependency
  18.   where  getCompileDependency(dependency)
  19.   select dependency,
  20.     "dependency: " +
  21.     dependency.getShortCoordinate()+":"+dependency.getVersionString()

④获取某方法的所有调用

  1. /**
  2.  * The class `com.xiaomi.miui.lockServer.utils. HttpUtils `.
  3.  */
  4. class TypeAbstractRequestMatcherRegistry extends Class {
  5.     TypeAbstractRequestMatcherRegistry() {
  6.       this.hasQualifiedName("com.xiaomi.miui.lockServer.utils",
  7.         "HttpUtils")
  8.     }
  9.   }
  10. /** A call to `HttpUtils. getRemoteUserIP ` method. */
  11. class AnyRequestCall extends MethodAccess {
  12.     AnyRequestCall() {
  13.       getMethod().hasName("getRemoteUserIP") and
  14.       getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry
  15.     }
  16.   }
  17. from Call c, Callable callee
  18. where callee = c.getCallee() and callee.getAReference() instanceof AnyRequestCall
  19. select c, "t:"+c.getQualifier()+" "+c.getCallee()
  20. //另外一种简便方式
  21. from Call c
  22. where c.getQualifier().toString() = "httpUtils" and c.getCallee().toString() = "getRemoteUserIP"
  23. select c, "t:"+c.getQualifier()+c.getCallee()

⑤获取某方法的调用链

  1. /**
  2.  * @name sectest2
  3.  * @description Writing sectest33
  4.  * @kind path-problem
  5.  * @problem.severity error
  6.  * @precision high
  7.  * @id java/sectest
  8.  * @tags security
  9.  *       external/cwe/cwe-113
  10.  */
  11. import java
  12. import semmle.code.java.dataflow.FlowSources
  13. import DataFlow::PathGraph
  14. class GetOrderIdByIMEIMethod extends Method {
  15.   GetOrderIdByIMEIMethod() {
  16.     getDeclaringType().hasQualifiedName("com.xiaomi.miui.lockServer.utils", "HttpUtils") and
  17.     hasName("getRemoteUserIP")
  18.   }
  19. }
  20. //ql自动调用实现类中的方法
  21. abstract class HeaderSplittingSink extends DataFlow::Node { }
  22. //sink为目标函数的参数
  23. class OrderHeaderSplittingSink extends HeaderSplittingSink{
  24.   OrderHeaderSplittingSink(){
  25.     exists(GetOrderIdByIMEIMethod m, MethodAccess ma |
  26.       ma.getMethod() = m and
  27.       this.asExpr() = ma.getArgument(0)
  28.     )
  29.   }
  30. }
  31. class ResponseSplittingConfig extends TaintTracking::Configuration {
  32.   ResponseSplittingConfig() { this = "ResponseSplittingConfig" }
  33.   override predicate isSource(DataFlow::Node source) {
  34.     //source instanceof RemoteFlowSource
  35.     exists(source.asExpr())
  36.   }
  37.   override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
  38. }
  39. from DataFlow::PathNode source, DataFlow::PathNode sink, ResponseSplittingConfig conf
  40. where conf.hasFlowPath(source, sink)
  41. select sink.getNode(), source, sink, "vulnerability due to this $@.",
  42.   source.getNode(), "user-provided value"

⑥判断参数值

MethodAccess ma | ma.getArgument(1).(StringLiteral).getValue() = "Nonex"

⑦嵌套类定义

  1. class JaxRsResponseBuilder2 extends Class {
  2.   JaxRsResponseBuilder2() { this.hasQualifiedName("javax.ws.rs.core", "Response$ResponseBuilder") }
  3. }

codeql安全能力

java

1、zip slip(zip解压覆盖任意文件)

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql

2、命令注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql

3、cookie安全

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-312/CleartextStorageCookie.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql

4、XSS

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-079/XSS.ql

5、依赖漏洞

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-1104/MavenPomDependsOnBintray.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql

6、反序列化

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql

7、http头注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql

8、url跳转

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql

9、ldap注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql

10、sql注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql

11、file权限&目录注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql

12、xml注入

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-611/XXE.ql

13、SSL校验

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql

14、弱加密

https://github.com/github/codeql/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql

15、随机数种子可预测

https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-335/PredictableSeed.ql

实战

宽泛的跨域配置

查看结果 https://lgtm.com/query/7135375648193136280/

代码:

  1. /**
  2. * @name access-control-allow-origin
  3. * @description set access-control-allow-origin with *
  4. * @kind problem
  5. * @problem.severity error
  6. * @precision high
  7. * @id java/corserror
  8. * @tags security
  9. * external/cwe/cwe-113
  10. */
  11. import java
  12. import semmle.code.java.dataflow.FlowSources
  13. class JaxRsResponseBuilder2 extends Class {
  14. JaxRsResponseBuilder2() { this.hasQualifiedName("javax.ws.rs.core", "Response$ResponseBuilder") }
  15. }
  16. class JaxRsResponseBuilderMethod extends Method {
  17. JaxRsResponseBuilderMethod() {
  18. getDeclaringType() instanceof JaxRsResponseBuilder2 and
  19. hasName("header")
  20. }
  21. }
  22. predicate broadCors(MethodAccess ma){
  23. exists(JaxRsResponseBuilderMethod m|
  24. ma.getMethod() = m and ma.getArgument(0).(StringLiteral).getValue().toLowerCase() = "access-control-allow-origin" and ma.getArgument(1).(StringLiteral).getValue() = "*"
  25. )
  26. }
  27. predicate broadCors2(MethodAccess ma){
  28. exists(ResponseSetHeaderMethod m|
  29. ma.getMethod() = m and ma.getArgument(0).(StringLiteral).getValue().toLowerCase() = "access-control-allow-origin" and ma.getArgument(1).(StringLiteral).getValue() = "*"
  30. )
  31. }
  32. predicate broadCors3(MethodAccess ma){
  33. exists(ResponseAddHeaderMethod m|
  34. ma.getMethod() = m and ma.getArgument(0).(StringLiteral).getValue().toLowerCase() = "access-control-allow-origin" and ma.getArgument(1).(StringLiteral).getValue() = "*"
  35. )
  36. }
  37. from MethodAccess ma
  38. where broadCors(ma) or broadCors2(ma) or broadCors3(ma)
  39. select ma, "CORS vulnerability due to this"+" "+ma.getCaller()

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/514694
推荐阅读
相关标签
  

闽ICP备14008679号