github / github/codeql

How can I "sanitize" paths where a variable is passed to a sanitization function, but the path doesn't contain the result of the sanitization function?

Aberta
#8,568 1 comentário 0 reações 0 responsáveis Ver no GitHub
question
Linguagem predominante
CodeQL
Estrelas
10.1k
Forks
2.1k
Merge médio
2d 15h
PRs com merge (30d)
141

Descrição

Update:

I'd like `SsaDefinition` and the `dominates` predicate to be better documented with some actual examples. See https://github.com/github/codeql/issues/8568#issuecomment-1084951233 for some more context.

---

Original Post:

I would like to remove/sanitize a path if the sink node was ever passed to the sanitization function sometime before reaching the sink. Here's an example of some C code I want to analyze:
```c
void sink(int);
void sanitize(int);

void foo(int x) {
sink(x);
}

void test(int x) {
// Alert
sink(x);

// Alert
foo(x);

sanitize(x);

// No alert
sink(x);

// No alert
foo(x);
}
```

If I use a simple `TaintTracking::Configuration` which tracks flows from the parameter `x` to the argument to `sink(x)`, I get four paths even if I use some type of sanitizer like this:
```ql
override predicate isSanitizer(DataFlow::Node sanitizer) {
exists(FunctionCall c | c.getTarget().hasName("sanitize") |
c.getAnArgument() = sanitizer.asExpr()
)
}
```

It makes sense why this doesn't work: each path goes directly from the parameter `x` to the argument of `sink` or `foo`. There are no paths that go from the parameter `x`, to `sanitize`, and then to the `sink` (that would be the case if the example had `sink(sanitize(x))`, but in this case `sanitize` does not return a value).

I can kind of get around this issue for cases where `sanitize` and `sink` are in the function call like this:
```ql
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall c | c.getTarget().hasName("sink") | c.getAnArgument() = sink.asExpr()) and
not exists(FunctionCall c |
c.getTarget().hasName("sanitize") and
sink.asExpr().getAPredecessor+() = c and
c.getAnArgument().(VariableAccess).getTarget() = sink.asExpr().(VariableAccess).getTarget()
)
}
```
With this I only get three paths instead of four, but I still don't get the desired two paths because it doesn't handle the general case where the sink and sanitizer are in two different functions.

Is there any way to solve this? Does CodeQL store any paths between _uses_ of a variables in addition to just the path from the definition of the variable to the use of it?

Guia de contribuição

Abrir o guia de contribuição

Direção de pesquisa

Leia as definições existentes de SsaDefinition e do predicado dominates e, em seguida, revise o contexto adicional no comentário 1084951233 da issue. Adicione documentação com exemplos concretos explicando como eles funcionam e como se aplicam ao caso de sanitization descrito; a issue estará concluída quando esses conceitos forem compreensíveis sem depender da discussão original.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Domínio
documentation
Tipo de issue
Documentação
Dificuldade
3/5
Tempo estimado
1-2 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.