abstract class PathCreation extends Expr {
abstract Expr getInput();
}
class PathsGet extends PathCreation, MethodAccess {
// 寻找`java.nio.file.Paths`类下的get方法
PathsGet() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypePaths and
m.getName() = "get"
)
}
// 返回这个方法的集合
override Expr getInput() { result = this.getAnArgument() }
}
class FileSystemGetPath extends PathCreation, MethodAccess {
// 寻找`java.nio.file.FileSystem`类下的getPath方法并通过getInput方法返回这个集合
FileSystemGetPath() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypeFileSystem and
m.getName() = "getPath"
)
}
override Expr getInput() { result = this.getAnArgument() }
}
class FileCreation extends PathCreation, ClassInstanceExpr {
// 限定实例化的对象的原型在`java.io.File`类下
// 例如new xxx() 这个xxx必须在`java.io.File`下
FileCreation() { this.getConstructedType() instanceof TypeFile }
override Expr getInput() {
// 获得上述实例化的class的参数,并且这个参数的类型必须是file类型的,并返回满足and条件的参数集合
result = this.getAnArgument() and
// Relevant arguments include those that are not a `File`.
not result.getType() instanceof TypeFile
}
}
class FileWriterCreation extends PathCreation, ClassInstanceExpr {
// 限定在`java.io.FileWriter`类下
FileWriterCreation() { this.getConstructedType().getQualifiedName() = "java.io.FileWriter" }
// 返回参数类型是String类型的参数
override Expr getInput() {
result = this.getAnArgument() and
// Relevant arguments are those of type `String`.
result.getType() instanceof TypeString
}
}
predicate inWeakCheck(Expr e) {
// None of these are sufficient to guarantee that a string is safe.
// 约束一个类下的方法如果是startswith等方法,注意这里的方法是原生的,这里建议扩大覆盖范围,使用matches去匹配类似的方法名
exists(MethodAccess m, Method def | m.getQualifier() = e and m.getMethod() = def |
def.getName() = "startsWith" or
def.getName() = "endsWith" or
def.getName() = "isEmpty" or
def.getName() = "equals"
)
or
// Checking against `null` has no bearing on path traversal.
exists(EqualityTest b | b.getAnOperand() = e | b.getAnOperand() instanceof NullLiteral)
}
// Ignore cases where the variable has been checked somehow,
// but allow some particularly obviously bad cases.
predicate guarded(VarAccess e) {
// 一个参数必须存在于上面抽象类返回结果的集合中且条件分支为True的情况下的方法,还要不是StartsWith等方法
exists(PathCreation p | e = p.getInput()) and
exists(ConditionBlock cb, Expr c |
cb.getCondition().getAChildExpr*() = c and
c = e.getVariable().getAnAccess() and
cb.controls(e.getBasicBlock(), true) and
// Disallow a few obviously bad checks.
not inWeakCheck(c)
)
}