codeql lab

CodeQL Lab

labs

https://lab.github.com/githubtraining/codeql-u-boot-challenge-(cc++)

classes: A class in codeql represents a collection of values satisfy some properties.

predicates: Predicates express logical properties of query

step-5

Write a query to find out macos

  • ntohs
  • ntohl
  • ntohll
1
2
3
4
5
6
import cpp
from Macro macro
where macro.getName() = "ntohs"
or macro.getName() = "ntohl"
or macro.getName() = "ntohll"
select macro

A more effective way:

1
2
3
4
5
import cpp

from Macro macro
where macro.getName() in ["ntohs", "ntohl", "ntohll"]
select macro

step-6

Find all the calls to memcpy

1
2
3
4
import cpp
from FunctionCall fc
where fc.getTarget().getName() = "memcpy"
select fc

step-7

Find all the invocations to ntoh* macros

1
2
3
4
import cpp
from MacroInvocation mi
where mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"]
select mi

step-8

find the top-level expression these macro invaocations expand to.

1
2
3
4
import cpp
from MacroInvocation mi
where mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"]
select mi.getExpr()

step-9

exists keyword, used to define a tempory varible in predicates.

1
2
3
from Person t
where exists(string c | t.getHairColor() = c)
select t

This query selects all persons with a hair color that is a string

define a class

https://codeql.github.com/docs/ql-language-reference/types/#classes

1
2
3
4
5
6
7
8
9
10
11
12
13
class OneTwoThree extends int {
OneTwoThree() { // characteristic predicate
this = 1 or this = 2 or this = 3
}

string getAString() { // member predicate
result = "One, two or three: " + this.toString()
}

predicate isEven() { // member predicate
this = 2
}
}

characteristic predicate, defined inside the body of class. They are logical perporties that use the variable this to restrict the possible values in the class.

1
2
3
4
5
6
7
8
9
10
11
12
import cpp
class NetworkByteSwap extends Expr {
NetworkByteSwap () {
exists( MacroInvocation mi |
this = mi.getExpr()
and mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"]
)
}
}

from NetworkByteSwap n
select n, "Network byte swap"

NetworkByteSwap represents all expressions that ntoh* macros expand to.

step-10 final step

Write a query to track the flow of tainted data from network controlled interges to the memcpy length argument. As a result, we will find 9 real vulnerabilities.

CodeQL’s taint tracking library can help us to achieve our goal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import cpp
import semmle.code.cpp.dataflow.TaintTracking
import DataFlow::PathGraph

class NetworkByteSwap extends Expr {
NetworkByteSwap () {
exists( MacroInvocation mi |
this = mi.getExpr()
and mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"]
)
}
}

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

override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof NetworkByteSwap
}

override predicate isSink(DataFlow::Node sink) {
// sink should be the size argument of calls to memcpy
(exists(FunctionCall call | sink.asExpr() = call.getArgument(2) and
call.getTarget().getName() = "memcpy"))
}
}

from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink, source, sink, "Network byte swap flows to memcpy"

isSource define a predicate to select collection of source data. In our goal, we can consider ntoh* macos as taint source.

isSink define a predicate to select collection of vulnerable target.We can consider

hasFlowPath holds true when tainted data from a given source flows to a sink.

Reference

https://securitylab.github.com/research/cve-2018-4259-macos-nfs-vulnerability/


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!