Skip to content
This repository has been archived by the owner on Oct 27, 2021. It is now read-only.

Commit

Permalink
Merge pull request #65 from joernio/claudiu/updateq
Browse files Browse the repository at this point in the history
Update queries to new format
  • Loading branch information
ursachec authored Mar 25, 2021
2 parents 2cc4d29 + 8d6a657 commit fc18867
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 219 deletions.
41 changes: 24 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,32 @@ as an example:
object Metrics extends QueryBundle {
@q
def tooManyParameters(n: Int = 4): Query = Query(
name = "too-many-parameters",
title = s"Number of parameters larger than $n",
description =
s"This query identifies functions with more than $n formal parameters",
score = 2.0, traversal = { cpg =>
cpg.method.filter(_.parameter.size > n)
}
)
def tooManyParameters(n: Int = 4): Query =
Query.make(
name = "too-many-params",
author = Crew.fabs,
title = s"Number of parameters larger than $n",
description = s"This query identifies functions with more than $n formal parameters",
score = 1.0,
withStrRep({ cpg =>
cpg.method.internal.filter(_.parameter.size > n)
}),
tags = List(QueryTags.metrics)
)
@q
def tooHighComplexity(n: Int = 4): Query = Query(
title = s"Cyclomatic complexity higher than $n",
description =
s"This query identifies functions with a cyclomatic complexity higher than $n",
score = 2.0, traversal = { cpg =>
cpg.method.filter(_.controlStructure.size > n)
}
)
def tooHighComplexity(n: Int = 4): Query =
Query.make(
name = "too-high-complexity",
author = Crew.fabs,
title = s"Cyclomatic complexity higher than $n",
description = s"This query identifies functions with a cyclomatic complexity higher than $n",
score = 1.0,
withStrRep({ cpg =>
cpg.method.internal.filter(_.controlStructure.size > n)
}),
tags = List(QueryTags.metrics)
)
...
}
```
Expand Down
2 changes: 1 addition & 1 deletion project/Versions.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Declare dependency versions in one place */
object Versions {
val cpg = "1.3.99"
val cpg = "1.3.102"
}
17 changes: 9 additions & 8 deletions src/main/scala/io/joern/scanners/c/CopyLoops.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ object CopyLoops extends QueryBundle {

@q
def isCopyLoop(): Query =
queryInit(
"copy-loop",
Crew.fabs,
"Copy loop detected",
"""
Query.make(
name = "copy-loop",
author = Crew.fabs,
title = "Copy loop detected",
description =
"""
|For (buf, indices) pairs, determine those inside control structures (for, while, if ...)
|where any of the calls made outside of the body (block) are Inc operations. Determine
|the first argument of that Inc operation and check if they are used as indices for
|the write operation into the buffer.
|""".stripMargin,
2, { cpg =>
score = 2,
withStrRep({ cpg =>
cpg.assignment.target.isArrayAccess
.map { access =>
(access.array, access.subscripts.code.toSet)
Expand All @@ -35,8 +37,7 @@ object CopyLoops extends QueryBundle {
(incIdentifiers & subscripts).nonEmpty
}
.map(_._1)
},
List()
}),
)

}
37 changes: 21 additions & 16 deletions src/main/scala/io/joern/scanners/c/CredentialDrop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,49 @@ object CredentialDrop extends QueryBundle {

@q
def userCredDrop(): Query =
queryInit(
"setuid-without-setgid",
Crew.malte,
"Process user ID is changed without changing groups first",
"""
Query.make(
name = "setuid-without-setgid",
author = Crew.malte,
title = "Process user ID is changed without changing groups first",
description =
"""
|The set*uid system calls do not affect the groups a process belongs to. However, often
|there exists a group that is equivalent to a user (e.g. wheel or shadow groups are often
|equivalent to the root user).
|Group membership can only be changed by the root user.
|Changes to the user should therefore always be preceded by calls to set*gid and setgroups,
|""".stripMargin,
2, { cpg =>
score = 2,
withStrRep({ cpg =>
cpg
.method("set(res|re|e|)uid")
.callIn
.whereNot(_.dominatedBy.isCall.name("set(res|re|e|)?gid"))
},
List(QueryTags.setxid)
}),
tags = List(QueryTags.setxid)
)

@q
def groupCredDrop(): Query =
queryInit(
"setgid-without-setgroups",
Crew.malte,
"Process group membership is changed without setting ancillary groups first",
"""
Query.make(
name = "setgid-without-setgroups",
author = Crew.malte,
title =
"Process group membership is changed without setting ancillary groups first",
description =
"""
|The set*gid system calls do not affect the ancillary groups a process belongs to.
|Changes to the group membership should therefore always be preceded by a call to setgroups.
|Otherwise the process may still be a secondary member of the group it tries to disavow.
|""".stripMargin,
2, { cpg =>
score = 2,
withStrRep({ cpg =>
cpg
.method("set(res|re|e|)gid")
.callIn
.whereNot(_.dominatedBy.isCall.name("setgroups"))
},
List(QueryTags.setxid)
}),
tags = List(QueryTags.setxid)
)

}
126 changes: 70 additions & 56 deletions src/main/scala/io/joern/scanners/c/DangerousFunctions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,37 @@ object DangerousFunctions extends QueryBundle {

@q
def getsUsed(): Query =
queryInit(
"call-to-gets",
Crew.suchakra,
"Dangerous function gets() used",
"""
Query.make(
name = "call-to-gets",
author = Crew.suchakra,
title = "Dangerous function gets() used",
description =
"""
| Avoid `gets` function as it can lead to reads beyond buffer
| boundary and cause
| buffer overflows. Some secure alternatives are `fgets` and `gets_s`.
|""".stripMargin,
8, { cpg =>
score = 8,
withStrRep({ cpg =>
cpg.method("gets").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def argvUsedInPrintf(): Query =
queryInit(
"format-controlled-printf",
Crew.suchakra,
"Non-constant format string passed to printf/sprintf/vsprintf",
"""
Query.make(
name = "format-controlled-printf",
author = Crew.suchakra,
title = "Non-constant format string passed to printf/sprintf/vsprintf",
description =
"""
| Avoid user controlled format strings like "argv" in printf, sprintf and vsprintf
| functions as they can cause memory corruption. Some secure
| alternatives are `snprintf` and `vsnprintf`.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg
.method("printf")
.callIn
Expand All @@ -46,94 +50,104 @@ object DangerousFunctions extends QueryBundle {
.method("(sprintf|vsprintf)")
.callIn
.whereNot(_.argument.order(2).isLiteral)
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def scanfUsed(): Query =
queryInit(
"call-to-scanf",
Crew.suchakra,
"Insecure function scanf() used",
"""
Query.make(
name = "call-to-scanf",
author = Crew.suchakra,
title = "Insecure function scanf() used",
description =
"""
| Avoid `scanf` function as it can lead to reads beyond buffer
| boundary and cause buffer overflows. A secure alternative is `fgets`.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg.method("scanf").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def strcatUsed(): Query =
queryInit(
"call-to-strcat",
Crew.suchakra,
"Dangerous functions `strcat` or `strncat` used",
"""
Query.make(
name = "call-to-strcat",
author = Crew.suchakra,
title = "Dangerous functions `strcat` or `strncat` used",
description =
"""
| Avoid `strcat` or `strncat` functions. These can be used insecurely
| causing non null-termianted strings leading to memory corruption.
| A secure alternative is `strcat_s`.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg.method("(strcat|strncat)").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def strcpyUsed(): Query =
queryInit(
"call-to-strcpy",
Crew.suchakra,
"Dangerous functions `strcpy` or `strncpy` used",
"""
Query.make(
name = "call-to-strcpy",
author = Crew.suchakra,
title = "Dangerous functions `strcpy` or `strncpy` used",
description =
"""
| Avoid `strcpy` or `strncpy` function. `strcpy` does not check buffer
| lengths.
| A possible mitigation could be `strncpy` which could prevent
| buffer overflows but does not null-terminate strings leading to
| memory corruption. A secure alternative (on BSD) is `strlcpy`.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg.method("(strcpy|strncpy)").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def strtokUsed(): Query =
queryInit(
"call-to-strtok",
Crew.suchakra,
"Dangerous function strtok() used",
"""
Query.make(
name = "call-to-strtok",
author = Crew.suchakra,
title = "Dangerous function strtok() used",
description =
"""
| Avoid `strtok` function as it modifies the original string in place
| and appends a null character after each token. This makes the
| original string unsafe. Suggested alternative is `strtok_r` with
| `saveptr`.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg.method("strtok").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

@q
def getwdUsed(): Query =
queryInit(
"call-to-getwd",
Crew.claudiu,
"Dangerous function getwd() used",
"""
Query.make(
name = "call-to-getwd",
author = Crew.claudiu,
title = "Dangerous function getwd() used",
description =
"""
| Avoid the `getwd` function, it does not check buffer lengths.
| Use `getcwd` instead, as it checks the buffer size.
|""".stripMargin,
4, { cpg =>
score = 4,
withStrRep({ cpg =>
cpg.method("getwd").callIn
},
List(QueryTags.badfn)
}),
tags = List(QueryTags.badfn)
)

}
17 changes: 9 additions & 8 deletions src/main/scala/io/joern/scanners/c/HeapBasedOverflow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ object HeapBasedOverflow extends QueryBundle {
* */
@q
def mallocMemcpyIntOverflow()(implicit context: EngineContext): Query =
queryInit(
"malloc-memcpy-int-overflow",
Crew.fabs,
"Dangerous copy-operation into heap-allocated buffer",
"-",
4, { cpg =>
Query.make(
name = "malloc-memcpy-int-overflow",
author = Crew.fabs,
title = "Dangerous copy-operation into heap-allocated buffer",
description = "-",
score = 4,
withStrRep({ cpg =>
val src = cpg
.method(".*malloc$")
.callIn
Expand All @@ -45,8 +46,8 @@ object HeapBasedOverflow extends QueryBundle {
.whereNot(_.argument(1).codeExact(memcpyCall.argument(3).code))
.hasNext
}
},
List(QueryTags.integers)
}),
tags = List(QueryTags.integers)
)

}
Loading

0 comments on commit fc18867

Please sign in to comment.