CodeQL复习:文件上传和 Fastjson

最近小弟 ch1e 开始学习codeql了,我也复习复习

Codeql 提供了非常方便的数据流分析功能,同时在官方库中,内置好了RemoteFlowSource,可以方便地获取外部输入,通常我们将他设置为source

文件上传

在 java 中的文件上传,通常在最后阶段都会调用文件操作类,一般有以下几种:

  1. JDK原始的java.io.FileInputStreamjava.io.FileOutputStream
  2. JDK原始的java.io.RandomAccessFile
  3. Apache Commons IO提供的org.apache.commons.io.FileUtils
  4. JDK1.7新增的基于NIO非阻塞异步读取文件的java.nio.channels.AsynchronousFileChannel
  5. JDK1.7新增的基于NIO读取文件的java.nio.file.Files
  6. java.io.File

这里以java.io.FileOutputStream为例,ql代码如下

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

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

    override predicate isSink(DataFlow::Node sink) {
        exists( MethodAccess call, Method method|  
            call.getMethod() = method and
            method.getDeclaringType().hasQualifiedName("java.io", "FileOutputStream") and
            sink.asExpr() = call.getAnArgument()
        )
    }
}

from FileUploadCheckConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink
where conf.hasFlowPath(source, sink)
select source, sink

sink设置为所调用的参数即可,结果

Fastjson

fastjson 中主要是判断是否调用了方法parse或者parseObject,同时输出fastjson的版本号

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

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

    override predicate isSink(DataFlow::Node sink) {
        exists( MethodAccess ma, Method m|  
            m.getDeclaringType().hasQualifiedName("com.alibaba.fastjson", ["JSON"])
            and ma.getMethod() = m
            and m.getName().regexpMatch("(parse|parseObject)")
            and sink.asExpr() = ma.getAnArgument()
        )
    }
}

from FastJsonDeserializationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink, PomDependency pd, string fastjson_version
where conf.hasFlowPath(source, sink) and pd.getGroup().getACharactersSet().toString() = "com.alibaba"
    and pd.getArtifact().getACharactersSet().toString() = "fastjson"
    and pd.getVersionString() = fastjson_version
select source, sink, fastjson_version

结果